RecyclerView 這一系列文章是基于一個示例, 可以忽略示例實現(xiàn)細節(jié).
主要關注通用點.
1. 實現(xiàn) DiffUtil.ItemCallback
在 Adapter 文件中盼铁, 創(chuàng)建頂級類
并將 數(shù)據(jù)類型 作為參數(shù)傳遞.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
需要實現(xiàn) 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 // 是否包含相同的數(shù)據(jù):SleepNight 是一個數(shù)據(jù)類,此相等性檢查將檢查所有字段(Data 類自動定義的)
}
}
2. 使用 ListAdapter 管理列表.
RecyclerView 提供適配器類 ListAdapter尝偎,可構(gòu)建由列表支持的 RecyclerView 適配器捉貌。
ListAdapter 會為跟蹤列表,并在列表更新時通知適配器。
2.1 ListAdapter 源碼分析
public abstract class ListAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
看一下源碼趁窃,它也是 繼承自 RecyclerView.Adapter.
特別地是, 泛型 T 類 作為 數(shù)據(jù)的類型.
因此可知, 它也會管理數(shù)據(jù)的.
它的構(gòu)造函數(shù)需要一個參數(shù) 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 表示 數(shù)據(jù)類型,
ViewHolder 原本的緩存
SleepNightDiffCallback 作為回調(diào)
2.3 刪除
SleepNightAdapter 中
(1)刪除 data字段, 因為 ListAdapter 會跟蹤列表
(2)刪除 getItemCount() , ListAdapter 已有實現(xiàn)
(3) 提供了 getItem, onBindViewHolder中使用它
2.4 使用 submitList() 及時更新列表
submitList() 的方法牧挣,用于告知 ListAdapter 列表有新版本。
調(diào)用此方法時:
(1)將新列表與舊列表進行差異比較,
并檢測已添加醒陆、移除瀑构、移動或更改的項
(2)更新 RecyclerView 所顯示的項
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
至此, 已經(jīng)完成了 DiffUtil 的使用.
主要是
(1)借助與 ListAdapter 的實現(xiàn), 將DiffUtil.ItemCallback 作為參數(shù)傳遞;
(2)然后在數(shù)據(jù)變化時, 調(diào)用 ListAdapter.submitList;
(3)此時會回調(diào)自定義的ItemCallback, 比較新表和舊表, 確定哪些需要更新
(4)RecyclerView 上僅更新上面確定更新的項.
--- End ---
參考指南:
https://developer.android.com/codelabs/kotlin-android-training-diffutil-databinding?hl=zh-cn#4