RecyclerView 这一系列文章是基于一个示例, 可以忽略示例实现细节.
主要关注通用点.
1. 实现 DiffUtil.ItemCallback
在 Adapter 文件中, 创建顶级类
并将 数据类型 作为参数传递.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
需要实现 ItemCallback 里的两个方法:
areItemsTheSame 和 areContentsTheSame
完整如下:
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>(){
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId // nightId 相同 则 认为 是相同的item
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem // 是否包含相同的数据:SleepNight 是一个数据类,此相等性检查将检查所有字段(Data 类自动定义的)
}
}
2. 使用 ListAdapter 管理列表.
RecyclerView 提供适配器类 ListAdapter,可构建由列表支持的 RecyclerView 适配器。
ListAdapter 会为跟踪列表,并在列表更新时通知适配器。
2.1 ListAdapter 源码分析
public abstract class ListAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
看一下源码,它也是 继承自 RecyclerView.Adapter.
特别地是, 泛型 T 类 作为 数据的类型.
因此可知, 它也会管理数据的.
它的构造函数需要一个参数 DiffUtil.ItemCallback
protected ListAdapter(@NonNull DiffUtil.ItemCallback<T> diffCallback) {
mHelper = new AsyncListDiffer<>(new AdapterListUpdateCallback(this),
new AsyncDifferConfig.Builder<>(diffCallback).build());
}
2.2 ListAdapter使用
修改成:
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
SleepNight 表示 数据类型,
ViewHolder 原本的缓存
SleepNightDiffCallback 作为回调
2.3 删除
SleepNightAdapter 中
(1)删除 data字段, 因为 ListAdapter 会跟踪列表
(2)删除 getItemCount() , ListAdapter 已有实现
(3) 提供了 getItem, onBindViewHolder中使用它
2.4 使用 submitList() 及时更新列表
submitList() 的方法,用于告知 ListAdapter 列表有新版本。
调用此方法时:
(1)将新列表与旧列表进行差异比较,
并检测已添加、移除、移动或更改的项
(2)更新 RecyclerView 所显示的项
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
至此, 已经完成了 DiffUtil 的使用.
主要是
(1)借助与 ListAdapter 的实现, 将DiffUtil.ItemCallback 作为参数传递;
(2)然后在数据变化时, 调用 ListAdapter.submitList;
(3)此时会回调自定义的ItemCallback, 比较新表和旧表, 确定哪些需要更新
(4)RecyclerView 上仅更新上面确定更新的项.
--- End ---
参考指南:
https://developer.android.com/codelabs/kotlin-android-training-diffutil-databinding?hl=zh-cn#4