RecyclerView局部刷新—AsyncListDiffer學習

踩坑android

  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已經提供的局部刷新功能git

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中展現的數據相同。github

Google提供了新的解決方案bash

  1. DiffUtil Android25.1.0添加
    • 須要繼承DiffUtil.Callback,提供新舊列表,並比較
    • 使用DiffUtil.calculateDiff進行比較,獲取DiffUtil.DiffResult
    • 調用Adapter.setData更改Adapter中的數據,注意,此處只是更改列表的數據,不能調用notifyDataSetChanged
    • 調用DiffResult.dispatchUpdatesTo(mAdapter);實現刷新UI

存在的問題ide

* calculateDiff在主線程,若是新舊數據差異很大,耗時長,會致使ANR
    * 最後須要調用dispatchUpdatesTo比較麻煩
複製代碼
  1. AsyncListDiffer Android27.1.0添加
    • 定義DiffUtil.ItemCallback實現比較
    • 在Adapter內部建立AsyncListDiffer
    • 使用mListDiffer.getCurrentList()和mListDiffer.submitList方式獲取數據和更新數據

解決辦法gradle

mListDiffer.submitList中使用線程進行的比較,使用主線程更新UIui

源碼以下url

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/…spa

參考:www.jianshu.com/p/66d0feab2…線程

相關文章
相關標籤/搜索