本文是介紹 RecyclerView 入門 系列文章 的第二篇奇唤。如果您已經(jīng)對創(chuàng)建 RecyclerView 有了一定的認(rèn)識,請繼續(xù)閱讀本文匹摇。如果尚未熟悉咬扇,建議您首先閱讀本系列中的 第一篇文章。
RecyclerView 可以很高效地顯示列表數(shù)據(jù)来惧。對于靜態(tài)的列表數(shù)據(jù)冗栗,默認(rèn)的 adapter 足矣。然而供搀,在多數(shù)情況下隅居,RecyclerView 的數(shù)據(jù)是動態(tài)變化的。拿備忘工作的應(yīng)用舉例: 主要操作是添加新的工作事項(xiàng)葛虐,刪除已經(jīng)完成的工作事項(xiàng)胎源。notifyItemInserted() 可以將新任務(wù)添加到指定位置,但是需要刪除元素的時(shí)候問題就來了屿脐,notifyItemRemoved() 只有在您已知待刪任務(wù)的位置時(shí)才有效果涕蚤。雖然可以寫代碼來確定待刪任務(wù)的位置,然后調(diào)用 notifyItemRemoved()的诵,但是代碼會變得非常繁雜万栅。調(diào)用 notifyDataSetChanged() 也是一個(gè)辦法,但是它會重繪整個(gè)視圖西疤,包括數(shù)據(jù)未發(fā)生變化的部分烦粒,使得該操作的代價(jià)變大。而 ListAdapter 可以處理元素的添加和刪除而無需重繪視圖代赁,甚至可以為變化添加動畫效果扰她。
使用 ListAdapter 的另一個(gè)好處是: 當(dāng)添加或刪除元素的時(shí)候,還可以添加動畫芭碍。這樣用戶可以很直觀地看到列表數(shù)據(jù)的變化徒役。雖然沒有 ListAdapter 也可以實(shí)現(xiàn)動畫效果,但是這就需要開發(fā)者自行實(shí)現(xiàn)窖壕,并且由于帶有動畫的視圖需要重繪忧勿,所以無法達(dá)到同樣的性能表現(xiàn)。
添加元素的動畫效果
處理差異比較
DiffUtil 是 ListAdapter 能夠高效改變元素的奧秘所在瞻讽。DiffUtil 會比較新舊列表中增加狐蜕、移動、刪除了哪些元素卸夕,然后輸出更新操作的列表將原列表中的元素高效地轉(zhuǎn)換為新的元素。
為了能夠識別新的數(shù)據(jù)婆瓜,DiffUtil 需要您重寫 areItemsTheSame() 和 areContentsTheSame()快集。areItemsTheSame() 檢查兩個(gè)元素是否為同一元素贡羔。areContentsTheSame() 檢查兩個(gè)元素是否包含相同的數(shù)據(jù)。
areItemsTheSame() 比較元素的示意圖
areContentsTheSame() 比較元素的示意圖
在 Adapter
類中添加 DiffUtil
對象个初,并且復(fù)寫 areItemsTheSame()
和 areContentsTheSame()
乖寒。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
object FlowerDiffCallback : DiffUtil.ItemCallback<Flower>() {
override fun areItemsTheSame(oldItem: Flower, newItem: Flower): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Flower, newItem: Flower): Boolean {
return oldItem == newItem
}
}
將 Adapter
的父類由 RecyclerView.Adapter
改為 ListAdapter
,并傳入 DiffCallback
院溺。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
class FlowerAdapter : ListAdapter<String, FlowerAdapter.FlowerViewHolder>(FlowerDiffCallback)
更新列表
ListAdapter 通過 submitList() 方法獲取數(shù)據(jù)楣嘁,該方法提交了一個(gè)列表來與當(dāng)前列表進(jìn)行對比并顯示。也就是說您無需再重寫 getItemCount()
珍逸,因?yàn)?ListAdapter
會負(fù)責(zé)管理列表逐虚。
在 Activity
類中,調(diào)用 Adapter
的 submitList()
方法并傳入數(shù)據(jù)列表谆膳。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
val flowerList = resources.getStringArray(R.array.flower_array).toMutableList()
val flowerAdapter = FlowerAdapter()
flowerAdapter.submitList(flowerList)
在 Adapter
類中叭爱,onBindViewHolder()
現(xiàn)在可以使用 getItem() 從數(shù)據(jù)列表中獲取指定位置的元素了。
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) {
holder.bind(getItem(position))
}
就這么簡單漱病。僅需幾步簡單操作就可以在您的 RecyclerView
中使用 ListAdapter
÷蛭恚現(xiàn)在您的應(yīng)用可以通過使用 ListAdapter
來更新那些發(fā)生變化的元素以獲得更好的性能和用戶體驗(yàn)了。
下一步
關(guān)于 ListAdapter
的 完整示例代碼 都在這里杨帽。
感謝閱讀 RecyclerView 系列 的第二篇文章漓穿。請繼續(xù)關(guān)注未來更多關(guān)于 RecyclerView
的內(nèi)容。
如果您想了解更多關(guān)于 ListAdapter
的內(nèi)容注盈,請參考 官方文檔晃危。