目录
概述
使用DiffUtil的原因是替代notifyDataSetChanged,提升性能。
DiffUtil使用的是Eugene Myers的差别算法,这个算法本身不能检查到元素的移动,也就是移动只能被算作先删除、再增加,而DiffUtil是在算法的结果后再
进行一次移动检查。假设在不检测元素移动的情况下,算法的时间复杂度为O(N + D2),而检测元素移动则复杂度为O(N2)。所以,如果集合本身就已经排好序,
可以不进行移动的检测提升效率。
ListAdapter和AsyncListDiffer中有使用。
使用
1 2 3 4 5 6 7 8 9 10 11 12
| public void swap(List newList) { MyDiffCallback callback = new MyDiffCallback(oldList, newList); DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback);
oldList.clear(); oldList.addAll(newList); result.dispatchUpdatesTo(this); }
|
使用的步骤:
- 实现DiffUtil.Callback
- 调用calculateDiff计算不同点
- dispatchUpdatesTo刷新数据
源码分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class DiffUtil {
public static DiffResult calculateDiff(@NonNull Callback cb) { return calculateDiff(cb, true); }
public abstract static class Callback { public abstract int getOldListSize(); public abstract int getNewListSize(); public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition); public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition); public Object getChangePayload(int oldItemPosition, int newItemPosition) { return null; } } public static class DiffResult { public void dispatchUpdatesTo(@NonNull ListUpdateCallback updateCallback) {} }
}
|
过程如下:
- 实现DiffUtil.Callback接口
- 新老数据集通过DiffUtil.calculateDiff计算得到DiffUtil.DiffResult
- DiffUtil.DiffResult::dispatchUpdatesTo刷新数据
参考