美文网首页
DiffUtil更新RecyclerView(深拷贝)

DiffUtil更新RecyclerView(深拷贝)

作者: 竹叶儿青 | 来源:发表于2020-06-10 14:36 被阅读0次

    一. 步骤

    1. 实现DiffUtil.Callback

    public class MovieDiffUtilCallback extends DiffUtil.Callback {
        private List<MovieListBean.M> oldList;
        private List<MovieListBean.M> newList;
    
        public MovieDiffUtilCallback(List<MovieListBean.M> oldList, List<MovieListBean.M> newList) {
            this.oldList = oldList;
            this.newList = newList;
        }
    
        @Override
        public int getOldListSize() {
            return oldList.size();
        }
    
        @Override
        public int getNewListSize() {
            return newList.size();
        }
    
        @Override
        public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        // 根据item的关键内容判断是否为同一个item
            return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
        }
    
        @Override
        public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        // 判断同一个item的内容是否相同,仅在areItemsTheSame为true时调用
            return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
        }
    
    // 比较得出应该更新的部分,仅在areItemsTheSame为true和areContentsTheSame为false时调用
    @Nullable
        @Override
        public Object getChangePayload(int oldItemPosition, int newItemPosition) {
            return super.getChangePayload(oldItemPosition, newItemPosition);
        }
    }
    

    2. 在RecyclerView的Adapter中重写onBindViewHolder(@NonNull MovieItemAndCastViewHolder holder, int position, @NonNull List<Object> payloads)方法:

    @Override
        public void onBindViewHolder(@NonNull MovieItemAndCastViewHolder holder, int position, @NonNull List<Object> payloads) {
      
            if (payloads.isEmpty()) {
                onBindViewHolder(holder, position, payloads);
            } else {
                MovieListBean.M m = (MovieListBean.M) payloads.get(0);
                holder.mainTitleTv.setText(m.getTitle());
            }
        }
    

    当padloads为空,表示没有数据要更新,调用2个参数的onBindViewHolder(@NonNull MovieItemAndCastViewHolder holder, int position)就行。
    若不为空,则更新holder的内容。
    3. 使用DiffResult更新数据

     @Override
        public void onMovieListDataSuccess(MovieListBean bean, int index) {
            // deep copy list
            List<MovieListBean.M> oldList = new ArrayList<>(mMovieList.size());
            oldList.addAll(mMovieList);
            mMovieList.addAll(bean.getResults());
            DiffUtil.DiffResult result = DiffUtil.calculateDiff(new MovieDiffUtilCallback(oldList, mMovieList), false);
            result.dispatchUpdatesTo(mAdapter);
        }
    

    这里new一个list用于存放旧的数据,然后addAll到oldList中,就是为了实现深拷贝的效果,如果直接令List<MovieListBean.M> oldList = mMovieList;mMovieList.addAll(bean.getResults());,这是浅拷贝,更改后的mMovieList会影响到oldList,使得计算更新失效,刷新有问题。

    我遇到的问题就是 浅拷贝导致更新有问题,需要把RecyclerView向上滑动一段距离然后再滑到底部才会显示更新的内容。

    相关文章

      网友评论

          本文标题:DiffUtil更新RecyclerView(深拷贝)

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