踩坑
- 目前Android28版本,源码还没发布,所以无法查看。虽然SDK Manager上显示下载且source目录下有,但无法关联查看。 所以想看源码请使用27版本。
- 切换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提供了新的解决方案
- DiffUtil Android25.1.0添加
- 需要继承DiffUtil.Callback,提供新旧列表,并比较
- 使用DiffUtil.calculateDiff进行比较,获取DiffUtil.DiffResult
- 调用Adapter.setData更改Adapter中的数据,注意,此处只是更改列表的数据,不能调用notifyDataSetChanged
- 调用DiffResult.dispatchUpdatesTo(mAdapter);实现刷新UI
存在的问题
* calculateDiff在主线程,如果新旧数据差别很大,耗时长,会导致ANR
* 最后需要调用dispatchUpdatesTo比较麻烦
复制代码
- 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);
}
}
});
}
});
}
复制代码