美文网首页
RecyclerView的局部更新

RecyclerView的局部更新

作者: _蘇芳_ | 来源:发表于2016-10-10 17:06 被阅读5726次

    我们知道recyclerView有好几个notify

    Paste_Image.png
    除了最常用的notifyDataSetChanged()以外,还有下面的那些,知道position就可以进行更新了
    但是!我得知道位置才能做到定向更新,那么我不想让所有都更新呢?
    实际开发中其实经常有这种情况,可能只是调整一小部分,根本不需要整体全部刷一遍,下面进入正题

    首先,项目里用到了

        compile 'com.android.support:appcompat-v7:24.2.1'
        compile 'io.reactivex.rxjava2:rxjava:2.0.0-RC4'
        compile 'io.reactivex.rxjava2:rxandroid:2.0.0-RC1'
        compile 'com.android.support:recyclerview-v7:24.2.1'
    

    当然rxjava不是必须的。。。不懂也没关系,这不是重点
    上代码,其实就2个类,一个MainActivity,一个是Adapter

    public class MainActivity extends AppCompatActivity {
        private RecyclerView mRv;
        private Button mBtn;
        private List<Bean> mDatas;
        private DiffAdapter diffAdapter;
        private List<Bean> mNewDatas;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
            initData();
            initEvent();
        }
    
        private void initView() {
            mRv = getView(R.id.rv);
            mBtn = getView(R.id.btn);
        }
    
        private void initData() {
            mDatas = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                //Bean就是个Bean类,里面就2个参数,一个id,一个name
                mDatas.add(new Bean(i, "name" + i));   
            }
        }
    
        private void initEvent() {
            mRv.setLayoutManager(new LinearLayoutManager(this));
            diffAdapter = new DiffAdapter(this, mDatas);
            mRv.setAdapter(diffAdapter);
            
            mBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    refresh();
                }
            });
        }
    
        private void refresh() {
            mNewDatas = new ArrayList<>();
            //模拟获取新数据,将原集合添加进来,删掉一个,添加一个
            mNewDatas.addAll(mDatas);                        
            mNewDatas.remove(0);
            Random random = new Random();
            int i = random.nextInt(10);
            mNewDatas.add(new Bean(i, "add" + i));
            //不懂rxjava的同学从这里
            Observable.fromArray(mDatas)                                       
                   .map(new Function<List<Bean>, DiffUtil.DiffResult>() {
                        @Override
                        public DiffUtil.DiffResult apply(List<Bean> been) throws Exception { 
                            //到这里可以不用看,下面的才是关键 
                            //DiffUtil.calculateDiff()是用来计算2个集合差异性的,返回了一个diffResult,下面会用到
                            return DiffUtil.calculateDiff(new DiffUtil.Callback() {                        
                                @Override
                                public int getOldListSize() {        //获取原集合大小
                                    return mDatas == null ? 0 : mDatas.size();
                                }
    
                                @Override
                                public int getNewListSize() {    //获取新集合大小
                                    return mNewDatas == null ? 0 : mNewDatas.size();
                                }
    
                                //判断2个item是否是同一个,逻辑根据实际开发需求来定,这里就用Bean.id来判断了
                                @Override
                                public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                                    return mDatas.get(oldItemPosition).getId() == mNewDatas.get(newItemPosition).getId();
                                }
                                
                                //判断2个item的内容是否改变了,同上,这里用Bean.name来判断
                                @Override
                                public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
                                    return TextUtils.equals(mDatas.get(oldItemPosition).getName(), mNewDatas.get(newItemPosition).getName());
                                }
    
                                /*如果2个item是同一个,但是内容不同,即
                                  areItemsTheSame 返回true
                                  areContentsTheSame 返回了false*/
                                //那么会调用这个方法
                                @Nullable
                                @Override
                                public Object getChangePayload(int oldItemPosition, int newItemPosition) {
                                    Bean oldBean = mDatas.get(oldItemPosition);
                                    Bean newBean = mNewDatas.get(newItemPosition);
                                    //将新旧2个item对象的不同之处返回,如果没有就返回null
                                   /*这个例子里面反正就一个name不同,就直接返回String了,
                                    如果变化的东西多,可以返回List,Map,SparseArray,bundle等等等等*/
                                    if (!TextUtils.equals(oldBean.getName(), newBean.getName())) {        
                                        return newBean.getName();
                                    } else {
                                        return null;
                                    }
                                }
                            });
                        }
                    })
                    .subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<DiffUtil.DiffResult>() {
                        @Override
                        public void accept(DiffUtil.DiffResult diffResult) throws Exception {
                        //上面的DiffUtil.calculateDiff()返回的diffResult这里用到了
                            diffResult.dispatchUpdatesTo(diffAdapter);
                            mDatas = mNewDatas;
                            diffAdapter.setData(mDatas);
                        }
                    });
            
        }
        
        private <T extends View> T getView(int id) {
            return (T)findViewById(id);
        }
    }
    
    public class DiffAdapter extends RecyclerView.Adapter<DiffAdapter.DiffVh> {
        private List<Bean> mDatas;
        private Context mContext;
        public DiffAdapter(Context context, List<Bean> datas) {
            mContext = context;
            mDatas = datas;
        }
    
        @Override
        public DiffAdapter.DiffVh onCreateViewHolder(ViewGroup parent, int viewType) {
            
            return new DiffVh(LayoutInflater.from(mContext).inflate(R.layout.item_rv,parent,false));
        }
    
        @Override
        public void onBindViewHolder(DiffAdapter.DiffVh holder, int position) {
            holder.tvTitle.setText(mDatas.get(position).getId()+"");
            holder.tvDesc.setText(mDatas.get(position).getName());
        }
    
        @Override
        public void onBindViewHolder(DiffAdapter.DiffVh holder, int position, List<Object> payloads) {
            if (payloads.isEmpty()) {
                onBindViewHolder(holder,position);
            }else {
                holder.tvDesc.setText((CharSequence) payloads.get(0));
            }
        }
    
        @Override
        public int getItemCount() {
            return mDatas==null?0:mDatas.size();
        }
    
        public void setData(List<Bean> mDatas) {
            this.mDatas = mDatas;
        }
    
        class DiffVh extends RecyclerView.ViewHolder {
    
            TextView tvTitle;
            TextView tvDesc;
    
            DiffVh(View itemView) {
                super(itemView);
                tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
                tvDesc = (TextView) itemView.findViewById(R.id.tv_desc);
            }
        }
    }
    

    布局文件不贴了吧
    R.layout.item_rv就是2个textview用来显示Bean的id和name
    R.layout.activity_main就是一个recyclerview和一个button用来刷新而已
    OK,到此为止,怎么用都在注释里

    相关文章

      网友评论

          本文标题:RecyclerView的局部更新

          本文链接:https://www.haomeiwen.com/subject/ugcvyttx.html