发布于:2021-02-16 00:00:58
0
368
0
作为Android开发人员,我们可以使用ListView或RecyclerView来实现滚动列表。让我们比较这两种方式,发现每个Android开发人员都应该知道的ListView和RecyclerView之间的5个关键区别。
ListView和RecyclerView–简史
作为Android开发人员,我们可以通过几种方式实现滚动列表,这主要取决于我们需要做什么。最流行的方法是使用ListView或Recycler视图。
ListView是一个很好的老部件,从API 1开始就包含在Android SDK中。在Android棒棒糖发布之前,我们主要使用的是这个API,它并没有那么糟糕,API基本上是直观的。不幸的是,它只允许我们创建元素的垂直滚动列表,为了使列表滚动顺利进行,我们必须记住正确地执行它。
此外,ListView类有点太重了,它有很多责任。无论何时我们必须处理列表,例如以某种方式配置它,唯一的方法就是通过ListView对象或在适配器内部。
现在我们用的是循环视图。正如我所提到的,它是在Android棒棒糖中引入的,它被证明是一个游戏规则的改变者。我们在ListView中讨厌的很多东西在RecyclerView中都被修复或更改了。默认情况下效率更高,布局是分开的,我们在适配器内的数据集上有更多的可能性。
如果您想了解更多关于ListView和RecyclerView的信息,可以看看我的文章,这些文章展示了如何实现ListView和如何实现RecyclerView。如果你是一个初学者,并且目标是提供最高级别的Android应用程序开发服务,那么它们都很有帮助。
在roid上的Droids,我们在所有领域的许多项目中使用RecyclerView,例如物联网应用程序开发、金融应用程序开发或移动商务应用程序开发。例如,我们在一个最大的项目中使用了它——开发CCC——这是中欧最大的鞋类零售公司的移动商务应用程序。
现在,让我们深入了解ListView和RecyclerView之间的区别。
ListView与RecyclerView–关键区别
1.ViewHolder
ViewHolder模式允许我们使列表滚动动作顺畅。它存储列表行视图引用,因此调用findViewById()
方法只会发生几次,而不是针对整个数据集和每个绑定视图。
RecyclerView的适配器强制我们使用ViewHolder模式。创建部分(扩展布局和查找视图)和更新视图分为两种方法-onCreateViewHolder()
和onBindViewHolder()
。
另一方面,ListView在默认情况下不会给我们提供这种保护,因此如果不在getView()
方法中实现ViewHolder模式,我们将以列表中低效的滚动结束。
2.LayoutManager
布局管理器负责布局行视图。因此,RecyclerView不必考虑如何定位行视图。这个类允许我们选择显示行视图的方式和滚动列表的方式。例如,如果要垂直或水平滚动列表,可以选择LinearLayoutManager。对于网格,更适合选择GridLayoutManager。
以前,使用ListView时,我们只能创建一个垂直滚动列表,所以没有那么灵活。如果我们想在列表中使用网格,我们必须为它选择另一个小部件-GridView。
3.ItemDecoration
ItemDecoration的职责在理论上很简单——为列表行视图添加一些装饰——但在实践中,如果我们想创建一个自定义的,实现起来就很简单。在这种情况下,我们应该扩展ItemDecoration类并实现我们的解决方案。例如,默认情况下,RecyclerView列表的行与行之间没有分隔符,并且它与材料设计准则一致。但是,如果出于某种原因要添加分隔符,可以使用DividerItemDecoration并将其添加到RecyclerView。
如果我们使用ListView,我们必须自己找出行。对于这个小部件,没有类似ItemDecoration的助手类。
4.ItemAnimator
我想提到的RecyclerView的最后一个组件是ItemAnimator。正如我们所料,它处理行视图动画,如列表的出现和消失,添加或删除特定的视图等等。
默认情况下,RecyclerView的列表动画是漂亮而平滑的。当然,我们可以通过创建自己的ItemAnimator来改变这一点,这也不是那么容易。为了更简单,我们应该扩展simpleItemImator类并实现所需的方法(只需将动画添加到ViewHolder的视图中)。
老实说,在ListView上实现动画是一件很麻烦的事。再说一次,我们必须想办法处理它们。没什么好东西。我很高兴它走了。
5.Notifying adapter
我们在RecyclerView的适配器上有几个很酷的通知程序。我们仍然可以使用notifyDataSetChanged()
,但也有一些用于特定列表元素,如notifyItemInserted()
、notifyItemRemoved()
甚至notifyItemChanged()
等等。我们应该为正在发生的事情使用最合适的动画,这样正确的动画就会正确地启动。
使用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为我们服务了很长一段时间。我们能处理大部分案件。但是现在用户的需求不同了,他们更具挑战性。列表设计变得越来越复杂,ListView无法帮助处理它们。材料设计也带来了其他的变化——它既美观又复杂。
幸运的是,引入了RecyclerView,解决了很多问题。默认情况下,它效率更高,动画更简单,布局更易于使用,API也更好。因此,如果你想知道应该选择哪一个,你的第一个想法应该是RecyclerView。我希望本文能帮助您理解ListView和RecyclerView之间的区别。
作者介绍