目录
- 场景介绍
- DiffUtil
- 怎么用
- 代码分析
- ReyclerView.ListAdapter
- 还是先来看看怎么用
- 源码分析
场景介绍
先介绍一下MVVM
我相信大家都已经非常熟悉了
ViewModel负责提供数据给View,通常我们会观察ViewModel的数据变化,当接收到了新数据后就刷新UI。
通常可能我们会这么写
//在View层观察数据
mViewModel.observeData().observe(activity, Observer { data->
//提交数据给adapter 更新UI
adapter.submitList(data)
})
//在Adapter中这么写
var mList: List<String>? = null
fun submitList(list: List<String>) {
mList = list
notifyDataSetChanged()
}
假设data1 和data2是这样的
val data1 = listOf("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "S", "Y", "Z")
val data2 = listOf( "K", "A", "b", "C", "Z", "E", "F", "G", "H", "I", "J","L", "m","N","P","P","Q","S","T","U","V","W","S","Y","A","C")
效果大概是这样的
我们可以看到,两个不同的数据data1,data2
有数据的移动,变化(大小写改变为变化),增加,删除
但是这些变化并没有很明显的展示出来,只是很生硬的一个视图的变化。
如果我们想让每个元素的增删改移都有对应的动画的话,怎么办呢?
大概是这样的一个效果
我们知道,要有增删改移的动画效果,需要我们调用RecyelerView.Adapter
的
public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)
public final void notifyItemChanged(int position)
public final void notifyItemMoved(int fromPosition, int toPosition)
那么问题就转化为,怎么快速的从data1
与data2
中找出哪个元素增加了、删除了、修改了、移动了
大家可以花一点时间思考一下这个问题,这个其实是一个非常复杂的差分问题
但!庆幸的是,Google官方为我们提供了DiffUtil
可以帮助我们进行这个操作
接下来介绍DiffUtil
DiffUtil
这个工具类是基于Eugene W. Myers的一篇论文