End

RV 数据刷新方式总结 局部刷新 模板代码

本文地址


目录

RV 数据刷新方式总结 局部刷新 模板代码

数据刷新方式总结 局部刷新

  • 刷新全部可见的item,notifyDataSetChanged()
  • 刷新指定item,notifyItemChanged(int)
  • 从指定位置开始刷新指定个item,notifyItemRangeChanged(int,int)
  • 插入、移动一个并自动刷新,notifyItemInserted(int)、notifyItemMoved(int)、notifyItemRemoved(int)
  • 局部刷新,notifyItemChanged(int, Object)

Activity

public class Notify_Activity extends Activity implements MyOnItemClickLitener {
    private RecyclerView mRecyclerView;
    private Notify_Adapter mAdapter;
    private ArrayList<PicUrls.BasicPicBean> beans;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((SwipeRefreshLayout) findViewById(R.id.swipeLayout)).setEnabled(false);
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        initList();
        initView();
    }
    
    protected void initView() {
        mAdapter = new Notify_Adapter(this, beans);
        mAdapter.setOnItemClickLitener(this);
        mRecyclerView.setAdapter(mAdapter);//设置adapter
        mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));//设置布局管理器
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());//设置Item增加、移除动画
        mRecyclerView.addItemDecoration(new GridItemDecoration.Builder().spanCount(3)
                .spaceSize(1).mDivider(new ColorDrawable(0x88ff0000)).build());
    }
    private void initList() {
        beans = PicUrls.getPicList(PicUrls.BIG_BEANS_2);
        beans.get(0).name = "刷新当前,notifyItemChanged(int)";
        beans.get(1).name = "全部刷新,notifyDataSetChanged()";
        beans.get(2).name = "从此位置开始刷新2个,notifyItemRangeChanged";
        beans.get(3).name = "插入一个并自动刷新,notifyItemInserted";
        beans.get(4).name = "只更改数据源,这样当然不会刷新UI";
        beans.get(5).name = "插入一个并刷新当前,notifyItemChanged";
        beans.get(6).name = "局部刷新,tv";
        beans.get(7).name = "局部刷新,et";
        beans.get(8).name = "局部刷新,iv";
    }
    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, position + " 被点击了", Toast.LENGTH_SHORT).show();
        reInit(position);
    }
    
    @Override
    public void onItemLongClick(View view, int position) {
        Toast.makeText(this, position + "被长按了", Toast.LENGTH_SHORT).show();
    }
    private void reInit(int position) {
        switch (position) {
            default:
                mAdapter.notifyItemChanged(position);//刷新指定一个。一定会闪
                break;
            case 1:
                mAdapter.notifyDataSetChanged();//全部刷新。基本不会闪,刚开始个别可能会闪
                break;
            case 2:
                mAdapter.notifyItemRangeChanged(position, 2);//从指定位置开始刷新指定个。一定会闪
                break;
            case 3:
                beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/1.jpg", "新插入的图片1", 1));
                mAdapter.notifyItemInserted(position);//插入一个并刷新,正常
                break;
            case 4://只更改数据源,这样当然不会刷新UI
                beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/2.jpg", "新插入的图片2", 2));
                break;
            case 5://
                beans.add(position, new PicUrls.BasicPicBean("http://img.mmjpg.com/2015/74/3.jpg", "新插入的图片3", 3));
                mAdapter.notifyItemChanged(position);//这样只会导致当前item刷新,而不会刷新其他item,当然是不行的
                break;
            case 6:
                beans.set(position, beans.get(new Random().nextInt(beans.size())));
                mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_TV);//局部刷新
                break;
            case 7:
                beans.set(position, beans.get(new Random().nextInt(beans.size())));
                mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_ET);//局部刷新
                break;
            case 8:
                beans.set(position, beans.get(new Random().nextInt(beans.size())));
                mAdapter.notifyItemChanged(position, Notify_Adapter.NOTIFY_IV);//局部刷新
                break;
        }
    }
}

Adapter

public class Notify_Adapter extends RecyclerView.Adapter<Notify_Adapter.MyViewHolder> {
    private Context context;
    private List<PicUrls.BasicPicBean> mDatas;
    private MyOnItemClickLitener mOnItemClickLitener;
    public static final int NOTIFY_TV = 10086;
    public static final int NOTIFY_ET = 10087;
    public static final int NOTIFY_IV = 10088;
    public Notify_Adapter(Context context, List<PicUrls.BasicPicBean> mDatas) {
        this.context = context;
        this.mDatas = mDatas;
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_notify, parent, false));
    }
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        //不使用
    }
    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position, List payloads) {
        //payloads是从notifyItemChanged(int, Object)中,或从notifyItemRangeChanged(int, int, Object)中传进来的Object集合
        //如果payloads不为空并且viewHolder已经绑定了旧数据了,那么adapter会使用payloads参数进行布局刷新
        //如果payloads为空,adapter就会重新绑定数据,也就是刷新整个item
        PicUrls.BasicPicBean bean = mDatas.get(holder.getAdapterPosition());
        long time = System.currentTimeMillis() + bean.url.hashCode();
        String data = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(time));
        if (payloads.isEmpty()) {//为空,即不是调用notifyItemChanged(position,payloads)后执行的,也即在初始化时执行的
            holder.tv.setText(data);
            holder.et.setText(bean.name);
            Glide.with(context).load(bean.url)
                    .dontAnimate()
                    //.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)
                    .into(holder.iv);
        } else if (payloads.size() > 0 && payloads.get(0) instanceof Integer) {
            //不为空,即调用notifyItemChanged(position,payloads)后执行的,可以在这里获取payloads中的数据进行局部刷新
            int type = (int) payloads.get(0);// 刷新哪个部分 标志位
            switch (type) {
                case NOTIFY_TV:
                    holder.tv.setText(data);//只刷新tv
                    break;
                case NOTIFY_ET:
                    holder.et.setText(bean.name);//只刷新et
                    break;
                case NOTIFY_IV:
                    Glide.with(context).load(bean.url).dontAnimate().into(holder.iv);//只刷新iv
                    break;
            }
        }
        // 如果设置了回调,则设置点击事件
        holder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnItemClickLitener != null) mOnItemClickLitener.onItemClick(holder.itemView, holder.getAdapterPosition());
            }
        });
        holder.itemView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mOnItemClickLitener != null) mOnItemClickLitener.onItemLongClick(holder.itemView, holder.getAdapterPosition());
                return false;
            }
        });
    }
    @Override
    public int getItemCount() {
        return mDatas.size();
    }
    /**
     * 添加并更新数据,同时具有动画效果
     */
    public void addDataAt(int position, PicUrls.BasicPicBean data) {
        mDatas.add(position, data);
        notifyItemInserted(position);//更新数据集,注意如果用adapter.notifyDataSetChanged()将没有动画效果
    }
    /**
     * 移除并更新数据,同时具有动画效果
     */
    public void removeDataAt(int position) {
        mDatas.remove(position);
        notifyItemRemoved(position);
    }
    public void setOnItemClickLitener(MyOnItemClickLitener mOnItemClickLitener) {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }
    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tv;
        ImageView iv;
        EditText et;
        public MyViewHolder(View view) {
            super(view);
            tv = (TextView) view.findViewById(R.id.tv_name);
            iv = (ImageView) view.findViewById(R.id.iv_head);
            et = (EditText) view.findViewById(R.id.et_input);
        }
    }
}

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:gravity="center_horizontal"
              android:orientation="vertical">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="0.00"
        android:textColor="#00f"
        android:textSize="13sp"/>
    <ImageView
        android:id="@+id/iv_head"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:src="@mipmap/ic_launcher"/>
    <EditText
        android:id="@+id/et_input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:hint="包青天"
        android:inputType="numberDecimal"
        android:labelFor="@id/et_input"
        android:maxLines="1"
        android:minWidth="50dp"
        android:textColor="#f00"
        android:textSize="10sp"/>
</LinearLayout>

模板代码

基础配置

implementation 'com.android.support:recyclerview-v7:27.1.1'
<android.support.v7.widget.RecyclerView
    android:id="@+id/rv_group"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="5dp"/>

纯原生

Activity

mAdapter = new RecyclerAdapter(this, list);
mAdapter.setOnItemClickLitener(this);

RecyclerView recyclerView = findViewById(R.id.rv_group);
recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
recyclerView.addItemDecoration(new DividerItemDecoration(mContext, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(mAdapter);

Adapter

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
    private Context context;
    private List<MyBean> mDatas;
    private MyOnItemClickLitener mOnItemClickLitener;
    
    public RecyclerAdapter(Context context, List<MyBean> mDatas) {
        this.context = context;
        this.mDatas = mDatas;
    }
    
    @NonNull 
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.bea_item_recycle, parent, false));
    }
    
    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
        holder.tv.setText(mDatas.get(position).name);
        
        // 如果设置了回调,则设置点击事件
        holder.itemView.setOnClickListener(v -> {
            if (mOnItemClickLitener != null) mOnItemClickLitener.onItemClick(holder.itemView, holder.getAdapterPosition());
        });
        holder.itemView.setOnLongClickListener(v -> {
            if (mOnItemClickLitener != null) mOnItemClickLitener.onItemLongClick(holder.itemView, holder.getAdapterPosition());
            return false;
        });
    }
    
    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public void setOnItemClickLitener(MyOnItemClickLitener mOnItemClickLitener) {
        this.mOnItemClickLitener = mOnItemClickLitener;
    }
    
    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tv;
        
        public MyViewHolder(View view) {
            super(view);
            tv = view.findViewById(R.id.tv_name);
        }
    }
    
    public interface MyOnItemClickLitener {
        void onItemClick(View view, int position);
        
        void onItemLongClick(View view, int position);
    }
}

BaseRecyclerViewAdapterHelper

依赖

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:VERSION_CODE'

Adapter

public class MyAdapter extends BaseQuickAdapter<MyBean, BaseViewHolder> {
    public MyAdapter(List<MyBean> datas) {
        super(R.layout.bea_item_recycle, datas);
    }
    
    @Override
    protected void convert(final BaseViewHolder helper, final MyBean item) {
        helper.setText(R.id.tv_name, item.name);
    }
}

Activity 中设置的点击事件

public class MyActivity implements BaseQuickAdapter.OnItemClickListener {
    mAdapter.setOnItemClickListener(this);
    
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
    }
}

点击事件可以通过如下几种方式设置:

mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {});
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {});
mAdapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {});
mAdapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {});

水平或竖直分割线

位置

compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'
RecyclerView.ItemDecoration decor = new HorizontalDividerItemDecoration.Builder(mContext)//不能Horizontal**和Vertical**同时使用
      .margin(SystemUtil.dp2px(15), SystemUtil.dp2px(2))//距离左右边界或上下边界的距离。也可以使用单参数的重载方法设定
      .size(SystemUtil.dp2px(1))//水平线的高度或竖直线的宽度
      .color(0xffe6e6e6)//间隔线的颜色。间隔线可以不使用颜色值而使用drawable方法指定drawable,同时使用时color()会把drawable()覆盖掉
      .positionInsideItem(false)//间隔线是否绘制在item内容的上面(也即不会增加RecyclerView的高度或宽度),默认为false
      //.showLastDivider()//默认不显示最后一条间隔线,调用此方法则会显示示最后一条间隔线
      .build();

其Builder中还有各种各级的用法

网格分割线

GridItemDecoration decoration = GridItemDecoration.newBuilder().spanCount(spanCount)
                        .horizontalDivider(new ColorDrawable(0xffff0000), 60, true)
                        .build();
GridItemDecoration decoration = GridItemDecoration.newBuilder().spanCount(spanCount)
                        .horizontalDivider(getResources().getDrawable(R.drawable.icon), 20, false)
                        .verticalDivider(new ColorDrawable(0xffff0000), 60, true)
                        .build();

2017-6-7

posted @ 2017-06-07 12:29  白乾涛  阅读(80435)  评论(0编辑  收藏  举报