RecyclerView 部件和功能

RecyclerView 在内部处理一些任务 (,例如滚动和回收视图) ,但它本质上是一个管理器来协调帮助程序类以显示集合。 RecyclerView 将任务委托给以下帮助程序类:

  • Adapter – 扩充项布局 (实例化布局文件) 的内容,并将数据绑定到 在 中显示的 RecyclerView视图。 适配器还会报告项单击事件。

  • LayoutManager – 度量和定位中的 RecyclerView 项视图,并管理视图回收策略。

  • ViewHolder - 查找和存储视图引用。 视图持有者还有助于检测项目视图单击次数。

  • ItemDecoration – 允许应用向特定视图添加特殊的绘图和布局偏移量,以便在项、突出显示和视觉分组边界之间绘制分隔线。

  • ItemAnimator – 定义在项操作期间或对适配器进行更改时发生的动画。

下图描述了 、 LayoutManagerAdapter 类之间的关系RecyclerView

包含 LayoutManager 的 RecyclerView 的示意图,使用适配器访问数据集

如此图所示, LayoutManager 可以视为 和 RecyclerView之间的Adapter中介。 代表 LayoutManager 对 方法RecyclerView进行调用Adapter。 例如, LayoutManager 当需要为 中的特定项位置创建新视图时, RecyclerView调用 Adapter 方法。 放大 Adapter 该项的布局,并创建一个 ViewHolder 实例, (不显示) 缓存对该位置的视图的引用。 LayoutManagerAdapter调用 以将特定项绑定到数据集时,会Adapter查找该项的数据,从数据集中检索数据,并将其复制到关联的项视图。

在应用中使用 RecyclerView 时,需要创建以下类的派生类型:

  • RecyclerView.Adapter – 提供从应用的数据集 (绑定,该绑定特定于你的应用,) 到 中显示的 RecyclerView项视图。 适配器知道如何将 中的每个 RecyclerView 项视图位置关联到数据源中的特定位置。 此外,适配器还处理每个单独的项目视图中内容的布局,并为每个视图创建视图持有者。 适配器还会报告项视图检测到的项单击事件。

  • RecyclerView.ViewHolder – 缓存对项布局文件中视图的引用,以便资源查找不会不必要地重复。 当用户点击视图持有人的关联项目视图时,视图持有者还会安排将项目单击事件转发到适配器。

  • RecyclerView.LayoutManager – 将项定位在 内 RecyclerView。 可以使用多个预定义布局管理器之一,也可以实现自己的自定义布局管理器。 RecyclerView 将布局策略委托给布局管理器,因此无需对应用进行重大更改即可插入其他布局管理器。

此外,还可以选择扩展以下类,以更改应用中的外观 RecyclerView

  • RecyclerView.ItemDecoration
  • RecyclerView.ItemAnimator

如果不扩展 ItemDecorationItemAnimatorRecyclerView 则使用默认实现。 本指南不介绍如何创建自定义 ItemDecoration 类和 ItemAnimator 类;有关这些类的详细信息,请参阅 RecyclerView.ItemDecorationRecyclerView.ItemAnimator

视图回收的工作原理

RecyclerView 不会为数据源中的每个项分配项视图。 相反,它只分配适合在屏幕上的项视图数,并在用户滚动时重复使用这些项目布局。 当视图首次滚动出视线时,它将经历下图所示的回收过程:

说明视图回收的六个步骤的关系图

  1. 当视图滚动出视线并且不再显示时,它将成为 废品视图

  2. 废品视图放置在池中,并成为 回收视图。 此池是显示相同数据类型的视图的缓存。

  3. 显示新项时,将从回收池中获取视图以供重复使用。 由于此视图必须在显示之前由适配器重新绑定,因此它称为脏视图

  4. 回收脏视图:适配器查找要显示的下一项的数据,并将此数据复制到该项目的视图。 这些视图的引用从与回收视图关联的视图持有者中检索。

  5. 回收的视图将添加到 中即将在屏幕上显示的项目 RecyclerView 列表中。

  6. 当用户滚动 RecyclerView 到列表中的下一项时,回收的视图将在屏幕上显示。 同时,另一个视图滚动出视线,并根据上述步骤回收。

除了项目视图重用外, RecyclerView 还使用另一个效率优化:视图持有者。 视图持有者是缓存视图引用的简单类。 每次适配器扩充项目布局文件时,它还会创建相应的视图持有者。 视图持有者使用 FindViewById 获取对膨胀项布局文件中视图的引用。 每次回收布局以显示新数据时,这些引用用于将新数据加载到视图中。

布局管理器

布局管理器负责在显示中 RecyclerView 定位项目;它确定列表或网格) (呈现类型、方向 (项目是垂直显示还是水平显示) ,以及哪些方向项应按正常顺序或反向顺序) (显示。 布局管理器还负责计算 RecycleView 显示中每个项的大小和位置。

布局管理器还有一个附加用途:它确定何时回收用户不再可见的项目视图的策略。 由于布局管理器知道哪些视图 (可见,哪些视图不) ,因此它最适合决定何时可以回收视图。 为了回收视图,布局管理器通常会调用适配器,以将已回收视图的内容替换为不同的数据,如前面 视图回收的工作原理中所述。

可以扩展 RecyclerView.LayoutManager 以创建自己的布局管理器,也可以使用预定义的布局管理器。 RecyclerView 提供以下预定义布局管理器:

  • LinearLayoutManager – 排列可垂直滚动的列或可水平滚动的行中的项。

  • GridLayoutManager – 显示网格中的项。

  • StaggeredGridLayoutManager – 在交错网格中显示项目,其中某些项具有不同的高度和宽度。

若要指定布局管理器,请实例化所选布局管理器并将其传递给 SetLayoutManager 方法。 请注意, 必须 指定布局管理器 - RecyclerView 默认情况下不选择预定义的布局管理器。

有关布局管理器的详细信息,请参阅 RecyclerView.LayoutManager 类参考

视图持有人

视图持有者是为缓存视图引用定义的类。 适配器使用这些视图引用将每个视图绑定到其内容。 中的每个 RecyclerView 项都有一个关联的视图持有者实例,用于缓存该项的视图引用。 若要创建视图持有者,请使用以下步骤定义一个类,以保存每个项的确切视图集:

  1. 子类 RecyclerView.ViewHolder
  2. 实现查找和存储视图引用的构造函数。
  3. 实现适配器可用于访问这些引用的属性。

基本回收器视图示例中ViewHolder提供了实现的详细示例。 有关 的详细信息 RecyclerView.ViewHolder,请参阅 RecyclerView.ViewHolder 类参考

适配器

大多数集成代码的 RecyclerView “繁重任务”都发生在适配器中。 RecyclerView 要求提供派生自 RecyclerView.Adapter 的适配器来访问数据源,并使用数据源中的内容填充每个项。 由于数据源特定于应用,因此必须实现了解如何访问数据的适配器功能。 适配器从数据源中提取信息,并将其加载到集合中的每个项中 RecyclerView

下图演示了适配器如何通过视图持有者将数据源中的内容映射到 中每个行项内的 RecyclerView单个视图:

说明将数据源连接到 ViewHolder 的适配器的关系图

适配器加载每 RecyclerView 一行以及特定行项的数据。 例如,对于行位置 P,适配器在数据源中的位置 P 处找到关联的数据,并将此数据复制到集合中位置 P 处的 RecyclerView 行项。 例如,在上面的绘图中,适配器使用视图持有人查找 位于该位置的 和 TextView 的引用ImageView,因此在用户滚动浏览集合并重用视图时,它不必重复调用FindViewById这些视图。

实现适配器时,必须重写以下 RecyclerView.Adapter 方法:

  • OnCreateViewHolder – 实例化项目布局文件和视图持有者。

  • OnBindViewHolder – 将指定位置的数据加载到其引用存储在给定视图持有者中的视图中。

  • ItemCount – 返回数据源中的项数。

布局管理器在 将项定位在 内 RecyclerView时调用这些方法。

通知 RecyclerView 数据更改

RecyclerView 当数据源的内容发生更改时,不会自动更新其显示;当数据集发生更改时,适配器必须发出通知 RecyclerView 。 数据集可以通过多种方式更改:例如,项内的内容可能会更改,或者数据的整体结构可能会更改。 RecyclerView.Adapter 提供了许多可以调用的方法, RecyclerView 以便以最有效的方式响应数据更改:

  • NotifyItemChanged – 指示位于指定位置的项已更改。

  • NotifyItemRangeChanged – 指示指定位置范围内的项已更改。

  • NotifyItemInserted – 指示指定位置的项已新插入。

  • NotifyItemRangeInserted – 指示指定位置范围内的项已新插入。

  • NotifyItemRemoved – 指示位于指定位置的项已被移除。

  • NotifyItemRangeRemoved – 指示指定位置范围内的项已被移除。

  • NotifyDataSetChanged – 指示数据集已更改 (强制) 完全更新。

如果确切地知道数据集的更改情况,则可以调用上述适当方法以最有效的方式刷新 RecyclerView 。 如果不知道数据集的确切变化情况,可以调用 NotifyDataSetChanged,这效率要低得多,因为 RecyclerView 必须刷新用户可见的所有视图。 有关这些方法的详细信息,请参阅 RecyclerView.Adapter

在下一主题 基本 RecyclerView 示例中,实现了一个示例应用来演示上面概述的部件和功能的真实代码示例。