RecyclerView局部刷新—AsyncListDiffer学习

踩坑

  1. 目前Android28版本,源码还没发布,所以无法查看。虽然SDK Manager上显示下载且source目录下有,但无法关联查看。 所以想看源码请使用27版本。
  2. 切换sdk时,导致/Library/Preferences/AndroidStudio3.3/options/jdk/jdk.table.xml中的sdk目前不正确,导致同步gradle时报错。找不到Android-27。
    <classPath>
          <root type="composite">
            <root url="jar://$USER_HOME$/Library/Android/sdk/platforms/android-27/android.jar!/" type="simple" />
            <root url="file://$USER_HOME$/Library/Android/sdk/platforms/android-27/data/res" type="simple" />
          </root>
    </classPath>
复制代码

RecyclerView已经提供的局部刷新功能

Adapter.notifyItemChanged(int)
Adapter.notifyItemInserted(int)
Adapter.notifyItemRangeChanged(int, int)
Adapter.notifyItemRangeInserted(int, int)
Adapter.notifyItemRangeRemoved(int, int)
复制代码

可见,局部刷新,需要指定Item的Position。所以如果更新的是整个列表的数据,则需要开发者计算需要刷新的Position。 否则使用Adapter.notifyDataSetChanged();会导致所有Item都刷新,即使新列表数据大部分和当前RecyclerView中展示的数据相同。

Google提供了新的解决方案

  1. DiffUtil Android25.1.0添加
    • 需要继承DiffUtil.Callback,提供新旧列表,并比较
    • 使用DiffUtil.calculateDiff进行比较,获取DiffUtil.DiffResult
    • 调用Adapter.setData更改Adapter中的数据,注意,此处只是更改列表的数据,不能调用notifyDataSetChanged
    • 调用DiffResult.dispatchUpdatesTo(mAdapter);实现刷新UI

存在的问题

    * calculateDiff在主线程,如果新旧数据差别很大,耗时长,会导致ANR
    * 最后需要调用dispatchUpdatesTo比较麻烦
复制代码
  1. AsyncListDiffer Android27.1.0添加
    • 定义DiffUtil.ItemCallback实现比较
    • 在Adapter内部创建AsyncListDiffer
    • 使用mListDiffer.getCurrentList()和mListDiffer.submitList方式获取数据和更新数据

解决办法

mListDiffer.submitList中使用线程进行的比较,使用主线程更新UI

源码如下

public void submitList(final List<T> newList) {
        if (newList == mList) {
            // nothing to do
            return;
        }

        // incrementing generation means any currently-running diffs are discarded when they finish
        final int runGeneration = ++mMaxScheduledGeneration;

        if (newList == null) {
            //noinspection ConstantConditions
            mUpdateCallback.onRemoved(0, mList.size());
            mList = null;
            mReadOnlyList = Collections.emptyList();
            return;
        }

        if (mList == null) {
            // fast simple first insert
            mUpdateCallback.onInserted(0, newList.size());
            mList = newList;
            mReadOnlyList = Collections.unmodifiableList(newList);
            return;
        }

        final List<T> oldList = mList;
        mConfig.getBackgroundThreadExecutor().execute(new Runnable() {
            @Override
            public void run() {
                final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
                    @Override
                    public int getOldListSize() {
                        return oldList.size();
                    }

                    @Override
                    public int getNewListSize() {
                        return newList.size();
                    }

                    @Override
                    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
                        return mConfig.getDiffCallback().areItemsTheSame(
                                oldList.get(oldItemPosition), newList.get(newItemPosition));
                    }

                    @Override
                    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
                        return mConfig.getDiffCallback().areContentsTheSame(
                                oldList.get(oldItemPosition), newList.get(newItemPosition));
                    }
                });

                mConfig.getMainThreadExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        if (mMaxScheduledGeneration == runGeneration) {
                            latchList(newList, result);
                        }
                    }
                });
            }
        });
    }
复制代码

例子: github.com/outman8511/…

参考:www.jianshu.com/p/66d0feab2…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值