本文是介紹 RecyclerView 入門 系列文章 的第二篇。若是您已經對建立 RecyclerView 有了必定的認識,請繼續閱讀本文。若是還沒有熟悉,建議您首先閱讀本系列中的 第一篇文章。java
RecyclerView 能夠很高效地顯示列表數據。對於靜態的列表數據,默認的 adapter 足矣。然而,在多數狀況下,RecyclerView 的數據是動態變化的。拿備忘工做的應用舉例: 主要操做是添加新的工做事項,刪除已經完成的工做事項。notifyItemInserted() 能夠將新任務添加到指定位置,可是須要刪除元素的時候問題就來了,notifyItemRemoved() 只有在您已知待刪任務的位置時纔有效果。雖然能夠寫代碼來肯定待刪任務的位置,而後調用 notifyItemRemoved(),可是代碼會變得很是繁雜。調用 notifyDataSetChanged() 也是一個辦法,可是它會重繪整個視圖,包括數據未發生變化的部分,使得該操做的代價變大。而 ListAdapter 能夠處理元素的添加和刪除而無需重繪視圖,甚至能夠爲變化添加動畫效果。android
使用 ListAdapter 的另外一個好處是: 當添加或刪除元素的時候,還能夠添加動畫。這樣用戶能夠很直觀地看到列表數據的變化。雖然沒有 ListAdapter 也能夠實現動畫效果,可是這就須要開發者自行實現,而且因爲帶有動畫的視圖須要重繪,因此沒法達到一樣的性能表現。git
添加元素的動畫效果
DiffUtil 是 ListAdapter 可以高效改變元素的奧祕所在。DiffUtil 會比較新舊列表中增長、移動、刪除了哪些元素,而後輸出更新操做的列表將原列表中的元素高效地轉換爲新的元素。github
爲了可以識別新的數據,DiffUtil 須要您重寫 areItemsTheSame() 和 areContentsTheSame()。areItemsTheSame() 檢查兩個元素是否爲同一元素。areContentsTheSame() 檢查兩個元素是否包含相同的數據。app
areItemsTheSame() 比較元素的示意圖
areContentsTheSame() 比較元素的示意圖
在 Adapter
類中添加 DiffUtil
對象,而且複寫 areItemsTheSame()
和 areContentsTheSame()
。ide
<!-- 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()) 方法獲取數據,該方法提交了一個列表來與當前列表進行對比並顯示。也就是說您無需再重寫 getItemCount()
,由於 ListAdapter
會負責管理列表。動畫
在 Activity
類中,調用 Adapter
的 submitList()
方法並傳入數據列表。google
<!-- 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()
如今可使用 getItem()) 從數據列表中獲取指定位置的元素了。spa
<!-- Copyright 2019 Google LLC. SPDX-License-Identifier: Apache-2.0 --> override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) { holder.bind(getItem(position)) }
就這麼簡單。僅需幾步簡單操做就能夠在您的 RecyclerView
中使用 ListAdapter
。如今您的應用能夠經過使用 ListAdapter
來更新那些發生變化的元素以得到更好的性能和用戶體驗了。
關於 ListAdapter
的 完整示例代碼 都在這裏。
感謝閱讀 RecyclerView 系列 的第二篇文章。請繼續關注將來更多關於 RecyclerView
的內容。
若是您想了解更多關於 ListAdapter
的內容,請參考 官方文檔。