發(fā)布于:2021-02-16 00:00:58
0
401
0
作為Android開發(fā)人員,我們可以使用ListView或RecyclerView來實現滾動列表。讓我們比較這兩種方式,發(fā)現每個Android開發(fā)人員都應該知道的ListView和RecyclerView之間的5個關鍵區(qū)別。
ListView和RecyclerView–簡史
作為Android開發(fā)人員,我們可以通過幾種方式實現滾動列表,這主要取決于我們需要做什么。最流行的方法是使用ListView或Recycler視圖。
ListView是一個很好的老部件,從API 1開始就包含在Android SDK中。在Android棒棒糖發(fā)布之前,我們主要使用的是這個API,它并沒有那么糟糕,API基本上是直觀的。不幸的是,它只允許我們創(chuàng)建元素的垂直滾動列表,為了使列表滾動順利進行,我們必須記住正確地執(zhí)行它。
此外,ListView類有點太重了,它有很多責任。無論何時我們必須處理列表,例如以某種方式配置它,唯一的方法就是通過ListView對象或在適配器內部。
現在我們用的是循環(huán)視圖。正如我所提到的,它是在Android棒棒糖中引入的,它被證明是一個游戲規(guī)則的改變者。我們在ListView中討厭的很多東西在RecyclerView中都被修復或更改了。默認情況下效率更高,布局是分開的,我們在適配器內的數據集上有更多的可能性。
如果您想了解更多關于ListView和RecyclerView的信息,可以看看我的文章,這些文章展示了如何實現ListView和如何實現RecyclerView。如果你是一個初學者,并且目標是提供最高級別的Android應用程序開發(fā)服務,那么它們都很有幫助。
在roid上的Droids,我們在所有領域的許多項目中使用RecyclerView,例如物聯網應用程序開發(fā)、金融應用程序開發(fā)或移動商務應用程序開發(fā)。例如,我們在一個最大的項目中使用了它——開發(fā)CCC——這是中歐最大的鞋類零售公司的移動商務應用程序。
現在,讓我們深入了解ListView和RecyclerView之間的區(qū)別。
ListView與RecyclerView–關鍵區(qū)別
1.ViewHolder
ViewHolder模式允許我們使列表滾動動作順暢。它存儲列表行視圖引用,因此調用findViewById()
方法只會發(fā)生幾次,而不是針對整個數據集和每個綁定視圖。
RecyclerView的適配器強制我們使用ViewHolder模式。創(chuàng)建部分(擴展布局和查找視圖)和更新視圖分為兩種方法-onCreateViewHolder()
和onBindViewHolder()
。
另一方面,ListView在默認情況下不會給我們提供這種保護,因此如果不在getView()
方法中實現ViewHolder模式,我們將以列表中低效的滾動結束。
2.LayoutManager
布局管理器負責布局行視圖。因此,RecyclerView不必考慮如何定位行視圖。這個類允許我們選擇顯示行視圖的方式和滾動列表的方式。例如,如果要垂直或水平滾動列表,可以選擇LinearLayoutManager。對于網格,更適合選擇GridLayoutManager。
以前,使用ListView時,我們只能創(chuàng)建一個垂直滾動列表,所以沒有那么靈活。如果我們想在列表中使用網格,我們必須為它選擇另一個小部件-GridView。
3.ItemDecoration
ItemDecoration的職責在理論上很簡單——為列表行視圖添加一些裝飾——但在實踐中,如果我們想創(chuàng)建一個自定義的,實現起來就很簡單。在這種情況下,我們應該擴展ItemDecoration類并實現我們的解決方案。例如,默認情況下,RecyclerView列表的行與行之間沒有分隔符,并且它與材料設計準則一致。但是,如果出于某種原因要添加分隔符,可以使用DividerItemDecoration并將其添加到RecyclerView。
如果我們使用ListView,我們必須自己找出行。對于這個小部件,沒有類似ItemDecoration的助手類。
4.ItemAnimator
我想提到的RecyclerView的最后一個組件是ItemAnimator。正如我們所料,它處理行視圖動畫,如列表的出現和消失,添加或刪除特定的視圖等等。
默認情況下,RecyclerView的列表動畫是漂亮而平滑的。當然,我們可以通過創(chuàng)建自己的ItemAnimator來改變這一點,這也不是那么容易。為了更簡單,我們應該擴展simpleItemImator類并實現所需的方法(只需將動畫添加到ViewHolder的視圖中)。
老實說,在ListView上實現動畫是一件很麻煩的事。再說一次,我們必須想辦法處理它們。沒什么好東西。我很高興它走了。
5.Notifying adapter
我們在RecyclerView的適配器上有幾個很酷的通知程序。我們仍然可以使用notifyDataSetChanged()
,但也有一些用于特定列表元素,如notifyItemInserted()
、notifyItemRemoved()
甚至notifyItemChanged()
等等。我們應該為正在發(fā)生的事情使用最合適的動畫,這樣正確的動畫就會正確地啟動。
使用ListView,我們只能在適配器上使用notifyDataSetChanged()
,然后又不得不自己處理其余部分。
關于RecyclerView的兩個有用提示
既然我們已經使用了RecyclerView,那么讓我們使用這個工具變得更簡單、更愉快就更好了。這里有幾個有用的特性。
1.DiffUtil.Callback
class DiffUtilCallback(
privateval oldItems: List,
privateval newItems: List
) : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldItems[oldItemPosition].id == newItems[newItemPosition].id
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
// It works properly if Item is a data class
// Otherwise, we should check if all fields of the items are the same
return oldItems[oldItemPosition] == newItems[newItemPosition]
}
override fun getOldListSize() = oldItems.size
override fun getNewListSize() = newItems.size
}
回調幫助我們跳過通知適配器的手動處理。我們不必為每種類型的通知使用不同的方法,如notifyItemInserted()
、notifyItemRemoved()
或notifyItemChanged()
,而只需使用以下簡單方法:
fun renderItems(newItems: List){
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(DiffUtilCallback(oldItems, newItems))
diffResult.dispatchUpdatesTo(this) // this : RecyclerView.Adapter
}
但即使是這種方法也不是終點.
2.ListAdapter
ListAdapter
是回收視圖上的套管。電源為DiffUtil
的適配器。由于ListAdapter
我們不需要:
保留項目列表字段
處理項目動畫
呈現新項目的寫入方法
關心項目列表的大小
它看起來怎么樣?我們需要定義三件事:兩種方法onCreateViewHolder
,onBindViewHolder
和DiffUtil.ItemCallback
(最簡單的DiffUtil.Callback
)。
示例代碼:
class Adapter : ListAdapter<Item, ItemViewHolder>(DiffUtilCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpotViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.bind(currentList[position])
}
object DiffUtilCallback : DiffUtil.ItemCallback() {
override fun areItemsTheSame(oldItem: Item, newItem: Item) = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Item, newItem: Item) = oldItem == newItem
}
}
對于新項目的渲染,使用ListAdapter
的adapter.submitList(newItems)
方法就足夠了。
使用RecyclerView從未如此簡單和愉快。
ListView與RecyclerView–總結
ListView為我們服務了很長一段時間。我們能處理大部分案件。但是現在用戶的需求不同了,他們更具挑戰(zhàn)性。列表設計變得越來越復雜,ListView無法幫助處理它們。材料設計也帶來了其他的變化——它既美觀又復雜。
幸運的是,引入了RecyclerView,解決了很多問題。默認情況下,它效率更高,動畫更簡單,布局更易于使用,API也更好。因此,如果你想知道應該選擇哪一個,你的第一個想法應該是RecyclerView。我希望本文能幫助您理解ListView和RecyclerView之間的區(qū)別。
作者介紹