ListView和RecyclerView有什么区别?

发布于:2021-02-16 00:00:58

0

368

0

Android 开发 ListView RecyclerView

作为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我们不需要:

  • 保留项目列表字段

  • 处理项目动画

  • 呈现新项目的写入方法

  • 关心项目列表的大小

它看起来怎么样?我们需要定义三件事:两种方法onCreateViewHolderonBindViewHolderDiffUtil.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
   }
}

对于新项目的渲染,使用ListAdapteradapter.submitList(newItems)方法就足够了。

使用RecyclerView从未如此简单和愉快。

ListView与RecyclerView–总结

ListView为我们服务了很长一段时间。我们能处理大部分案件。但是现在用户的需求不同了,他们更具挑战性。列表设计变得越来越复杂,ListView无法帮助处理它们。材料设计也带来了其他的变化——它既美观又复杂。

幸运的是,引入了RecyclerView,解决了很多问题。默认情况下,它效率更高,动画更简单,布局更易于使用,API也更好。因此,如果你想知道应该选择哪一个,你的第一个想法应该是RecyclerView。我希望本文能帮助您理解ListView和RecyclerView之间的区别。