背景
首页列表变量更新,首页的上半身是个列表,列表根据变化内容刷新是必要的;但如果全量更新,则会产生不必要的性能损耗。
通常,用户的每多一次下拉刷新,首页区块都无需更新。
搭建基础diff工具类,diff的应用场景很广泛,两组字符串、两个列表之间有何变化都可能需要做diff分析,平台有必要搭建这样一个不受限于业务和具体UI控件的工具类供业务方使用。
Diff工具类
Android中的diff工具类已经存在,比如下面两个:
DiffUtil
DiffUtil
,用于比较两个数据集,寻找出旧数据集->新数据集的最小变化量。
它的出现满足了数据集变量更新的诉求,并填补了RecyclerView的以下缺陷:
- 如果使用
notifyDataSetChanged()
全量更新数据,性能则会变差,同时变更动画将失效 - 如果使用
notifyItemRangeXxx()
变量更新数据,成本则会增大,因为业务层需要计算出变更的数据项
AsyncListDiffer
AsyncListDiffer
,它是DiffUtil的进化版,在后台线程使用DiffUtil计算diff的最小量,同时又在主线程中将更新操作的最小量分发给ListUpdateCallback,以完成数据更新,从而弥补了DiffUtil的缺陷。
那么已经有了如此好的工具,我们直接用于首页列表的diff可不可以呢?
“可以”;但是,DiffUtil存在弊端,其内部引用了RecyclerView的Adapter,与View层产生高度耦合。作为工具类,这种设计是过度封装的,不好扩展和移植。
此时,我们也想进一步了解DiffUtil的实现机制,考虑做一个与View层无耦合的diff工具类,这样可以更好地进行代码扩展和移植。
DiffUtil的算法
Diff的核心是差分算法,DiffUtil的算法则是著名的Myers差分算法。它有两个特性:
- 计算出了最小的变化量,而且随变化量越小时间复杂度越低
- 直观,计算出的变化内容看起来要比其他算法更容易理解
Myers算法原理及推导
推导
图形解释
“直观”是Myers的特性
- Git生成diff为什么会用到Myers
首页列表的diff