RecyclerView | 在 RecyclerView 中使用 ListAdapter

本文是介绍 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() 比较元素的示意图

areItemsTheSame() 比较元素的示意图

areContentsTheSame() 比较元素的示意图

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 类中,调用 AdaptersubmitList() 方法并传入数据列表。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 的内容,请参考 官方文档