notifydatasetchanged(notifydatasetchanged 卡顿)

zhangyang 2022-05-10 阅读:29
  

RecyclerView  | 在 RecyclerView  中使用 ListAdapter

  本文是关于RecyclerView的介绍性文章系列的第二篇。如果您已经对创建RecyclerView有所了解,请继续阅读本文。如果你不熟悉,建议你先看这个系列的第一篇文章。

  RecyclerView可以非常高效地显示列表数据。对于静态列表数据,默认适配器就足够了。然而,在大多数情况下,RecyclerView的数据是动态的。以备忘工作的应用为例。的主要操作是添加新的工作项和删除已完成的工作项。NotifyItemInserted()可以向指定位置添加新任务,但是当需要删除元素时问题就来了。notifyItemRemoved()仅在您知道要删除的任务的位置时才起作用。虽然可以编写代码来确定要删除的任务的位置,然后调用notifyItemRemoved(),但是代码会变得非常复杂。调用notifyDataSetChanged()也是一个选项,但是它会重绘整个视图,包括数据未改变的部分,这使得操作开销更大。ListAdapter可以在不重绘视图的情况下处理元素的添加和删除,甚至可以为更改添加动画效果。

  使用ListAdapter的另一个好处是,在添加或删除元素时还可以添加动画。这样,用户可以直观地看到列表数据的变化。虽然不用ListAdapter也能实现动画效果,但是需要开发者自己实现,同样的性能是无法实现的,因为带动画的视图需要重画。

RecyclerView  | 在 RecyclerView  中使用 ListAdapter

  添加元素的动画效果。

  添加元素的动画效果。

处理差异比较

   DiffUtil是ListAdapter能够高效改变元素的秘诀。DiffUtil比较新旧列表中添加、移动或删除了哪些元素,然后输出更新操作列表,以高效地将原始列表中的元素转换为新元素。

  为了能够识别新数据,DiffUtil要求您重写areItemsTheSame()和areContentsTheSame()。AreItemsTheSame()检查两个元素是否相同。AreContentsTheSame()检查两个元素是否包含相同的数据。

RecyclerView  | 在 RecyclerView  中使用 ListAdapter

   areitemname()的比较元素示意图

RecyclerView  | 在 RecyclerView  中使用 ListAdapter

   arecontthesame()比较元件示意图

  在适配器类中添加DiffUtil对象,并重写areItemsTheSame()和areContentsTheSame()。

  !-版权所有2019GoogleLLC。

  SPDX-许可证标识符:Apache-2.0 -

  objectFlowerDiffCa

llback : 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 类中,调用 AdaptersubmitList() 方法并传入数据列表。

<!-- 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() 从数据列表中获取指定位置的元素了。

<!-- 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 的内容,请参考 官方文档。

评论(0)

二维码