RecyclerView 部件和功能RecyclerView Parts and Functionality

RecyclerView 可以在内部处理某些任务(如视图的滚动和回收),但是它实质上是协调 helper 类以显示集合的管理器。RecyclerView handles some tasks internally (such as the scrolling and recycling of views), but it is essentially a manager that coordinates helper classes to display a collection. RecyclerView 将任务委托给以下 helper 类:RecyclerView delegates tasks to the following helper classes:

  • Adapter – 增加项布局(实例化布局文件的内容),并将数据绑定到 RecyclerView中显示的视图。Adapter – Inflates item layouts (instantiates the contents of a layout file) and binds data to views that are displayed within a RecyclerView. 适配器还会报告项目单击事件。The adapter also reports item-click events.

  • LayoutManager – 度量和定位 RecyclerView 内的项视图,并管理视图回收策略。LayoutManager – Measures and positions item views within a RecyclerView and manages the policy for view recycling.

  • ViewHolder – 查找并存储视图引用。ViewHolder – Looks up and stores view references. 视图刀柄还有助于检测项目-查看单击。The view holder also helps with detecting item-view clicks.

  • ItemDecoration – 允许应用向特定视图添加特殊的绘图和布局偏移量,以便在项、突出显示和视觉分组边界之间绘制分隔线。ItemDecoration – Allows an app to add special drawing and layout offsets to specific views for drawing dividers between items, highlights, and visual grouping boundaries.

  • ItemAnimator – 定义在项操作期间或对适配器进行更改时所发生的动画。ItemAnimator – Defines the animations that take place during item actions or as changes are made to the adapter.

下图描述了 RecyclerViewLayoutManagerAdapter 类之间的关系:The relationship between the RecyclerView, LayoutManager, and Adapter classes is depicted in the following diagram:

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

如图所示,可以将 LayoutManager 视为 AdapterRecyclerView之间的中介。As this figure illustrates, the LayoutManager can be thought of as the intermediary between the Adapter and the RecyclerView. LayoutManager 代表 RecyclerViewAdapter 方法进行调用。The LayoutManager makes calls into Adapter methods on behalf of the RecyclerView. 例如,当需要为 RecyclerView中的特定项位置创建新的视图时,LayoutManager 将调用 Adapter 方法。For example, the LayoutManager calls an Adapter method when it is time to create a new view for a particular item position in the RecyclerView. Adapter 增加该项目的布局,并创建 ViewHolder 实例(未显示)来缓存对该位置的视图的引用。The Adapter inflates the layout for that item and creates a ViewHolder instance (not shown) to cache references to the views at that position. LayoutManager 调用 Adapter 将特定项绑定到数据集时,Adapter 将查找该项的数据,从数据集中检索数据,并将其复制到关联的项视图。When the LayoutManager calls the Adapter to bind a particular item to the data set, the Adapter locates the data for that item, retrieves it from the data set, and copies it to the associated item view.

在应用中使用 RecyclerView 时,需要创建以下类的派生类型:When using RecyclerView in your app, creating derived types of the following classes is required:

  • RecyclerView.Adapter – 提供从应用的数据集(特定于应用)到在 RecyclerView中显示的项视图的绑定。RecyclerView.Adapter – Provides a binding from your app's data set (which is specific to your app) to item views that are displayed within the RecyclerView. 适配器知道如何将 RecyclerView 中的每个项视图位置关联到数据源中的特定位置。The adapter knows how to associate each item-view position in the RecyclerView to a specific location in the data source. 此外,适配器还处理每个单独项视图中内容的布局,并为每个视图创建视图占位符。In addition, the adapter handles the layout of the contents within each individual item view and creates the view holder for each view. 适配器还会报告项目视图检测到的项目单击事件。The adapter also reports item-click events that are detected by the item view.

  • RecyclerView.ViewHolder – 将对项布局文件中的视图进行缓存引用,以便不会重复进行资源查找。RecyclerView.ViewHolder – Caches references to the views in your item layout file so that resource lookups are not repeated unnecessarily. 视图容纳器还会安排在用户点击视图持有者的关联项视图时,将其转发到适配器。The view holder also arranges for item-click events to be forwarded to the adapter when a user taps the view-holder's associated item view.

  • RecyclerView.LayoutManager – 在 RecyclerView中定位项。RecyclerView.LayoutManager – Positions items within the RecyclerView. 您可以使用几个预定义的布局管理器之一,也可以实现您自己的自定义布局管理器。You can use one of several predefined layout managers or you can implement your own custom layout manager. RecyclerView 将布局策略委托给布局管理器,因此你可以插入不同的布局管理器,而无需对应用进行重大更改。RecyclerView delegates the layout policy to the layout manager, so you can plug in a different layout manager without having to make significant changes to your app.

此外,还可以选择扩展以下类,以更改应用程序中 RecyclerView 的外观和感觉:Also, you can optionally extend the following classes to change the look and feel of RecyclerView in your app:

  • RecyclerView.ItemDecoration
  • RecyclerView.ItemAnimator

如果不扩展 ItemDecorationItemAnimatorRecyclerView 将使用默认实现。If you do not extend ItemDecoration and ItemAnimator, RecyclerView uses default implementations. 本指南不介绍如何创建自定义 ItemDecorationItemAnimator 类;有关这些类的详细信息,请参阅RecyclerView. ItemDecoration and RecyclerViewThis guide does not explain how to create custom ItemDecoration and ItemAnimator classes; for more information about these classes, see RecyclerView.ItemDecoration and RecyclerView.ItemAnimator.

视图回收的工作原理How View Recycling Works

RecyclerView 不会为数据源中的每个项分配项视图。RecyclerView does not allocate an item view for every item in your data source. 相反,它仅分配适合屏幕的项视图数,并在用户滚动时重用这些项布局。Instead, it allocates only the number of item views that fit on the screen and it reuses those item layouts as the user scrolls. 当视图第一次滚动时,它会经历下图所示的回收过程:When the view first scrolls out of sight, it goes through the recycling process illustrated in the following figure:

说明查看回收的六个步骤的关系图Diagram illustrating the six steps of view recycling

  1. 当视图在视觉上滚动并不再显示时,它将成为一个废料视图When a view scrolls out of sight and is no longer displayed, it becomes a scrap view.

  2. "碎片" 视图放置在一个池中,并成为回收视图The scrap view is placed in a pool and becomes a recycle view. 此池是显示相同数据类型的视图缓存。This pool is a cache of views that display the same type of data.

  3. 当显示新项时,将从回收池中获取视图以供重用。When a new item is to be displayed, a view is taken from the recycle pool for reuse. 因为此视图必须在适配器重新绑定后才能显示,所以称为 "脏视图"。Because this view must be re-bound by the adapter before being displayed, it is called a dirty view.

  4. 已回收脏视图:适配器查找要显示的下一项的数据,并将此数据复制到此项的视图。The dirty view is recycled: the adapter locates the data for the next item to be displayed and copies this data to the views for this item. 这些视图的引用将从与回收视图关联的视图持有者中进行检索。References for these views are retrieved from the view holder associated with the recycled view.

  5. 回收视图将添加到要在屏幕上显示的 RecyclerView 中的项列表。The recycled view is added to the list of items in the RecyclerView that are about to go on-screen.

  6. 当用户将 RecyclerView 滚动到列表中的下一项时,回收视图将在屏幕上显示。The recycled view goes on-screen as the user scrolls the RecyclerView to the next item in the list. 同时,另一个视图会滚动显示,并根据以上步骤进行回收。Meanwhile, another view scrolls out of sight and is recycled according to the above steps.

除了项目视图重用外,RecyclerView 还使用另一个效率优化:查看持有者。In addition to item-view reuse, RecyclerView also uses another efficiency optimization: view holders. 视图占位符是缓存视图引用的简单类。A view holder is a simple class that caches view references. 每次适配器增加项布局文件时,它也会创建相应的视图持有者。Each time the adapter inflates an item-layout file, it also creates a corresponding view holder. 视图占位符使用 FindViewById 获取对放大的项布局文件中的视图的引用。The view holder uses FindViewById to get references to the views inside the inflated item-layout file. 每次回收布局以显示新数据时,这些引用用于将新数据加载到视图中。These references are used to load new data into the views every time the layout is recycled to show new data.

布局管理器The Layout Manager

布局管理器负责在 RecyclerView 显示中定位项;它确定表示类型(列表或网格)、方向(是垂直显示还是水平显示项)以及应显示的方向项(按正常顺序或逆序显示)。The layout manager is responsible for positioning items in the RecyclerView display; it determines the presentation type (a list or a grid), the orientation (whether items are displayed vertically or horizontally), and which direction items should be displayed (in normal order or in reverse order). 布局管理器还负责计算RecycleView显示中每个项的大小和位置。The layout manager is also responsible for calculating the size and position of each item in the RecycleView display.

布局管理器有一个额外的用途:它确定何时回收不再向用户显示的项视图的策略。The layout manager has an additional purpose: it determines the policy for when to recycle item views that are no longer visible to the user. 由于布局管理器识别哪些视图是可见的(而不是),因此,它在确定何时可以回收视图的最佳位置。Because the layout manager is aware of which views are visible (and which are not), it is in the best position to decide when a view can be recycled. 若要回收视图,布局管理器通常会调用适配器,以将回收视图的内容替换为不同的数据,如前面的视图回收的工作原理中所述。To recycle a view, the layout manager typically makes calls to the adapter to replace the contents of a recycled view with different data, as described previously in How View Recycling Works.

您可以扩展 RecyclerView.LayoutManager 来创建自己的布局管理器,也可以使用预定义的布局管理器。You can extend RecyclerView.LayoutManager to create your own layout manager, or you can use a predefined layout manager. RecyclerView 提供以下预定义的布局管理器:RecyclerView provides the following predefined layout managers:

  • LinearLayoutManager – 可以在垂直滚动的列中或在可水平滚动的行中排列项。LinearLayoutManager – Arranges items in a column that can be scrolled vertically, or in a row that can be scrolled horizontally.

  • GridLayoutManager – 在网格中显示项。GridLayoutManager – Displays items in a grid.

  • StaggeredGridLayoutManager – 在交错的网格中显示项,其中某些项具有不同的高度和宽度。StaggeredGridLayoutManager – Displays items in a staggered grid, where some items have different heights and widths.

若要指定布局管理器,请实例化所选的布局管理器,并将其传递给 SetLayoutManager 方法。To specify the layout manager, instantiate your chosen layout manager and pass it to the SetLayoutManager method. 请注意,必须指定布局管理器 – RecyclerView 默认情况下未选择预定义的布局管理器。Note that you must specify the layout manager – RecyclerView does not select a predefined layout manager by default.

有关布局管理器的详细信息,请参阅RecyclerView. LayoutManager 类引用For more information about the layout manager, see the RecyclerView.LayoutManager class reference.

视图持有者The View Holder

视图占位符是您为缓存视图引用定义的类。The view holder is a class that you define for caching view references. 适配器使用这些视图引用将每个视图绑定到其内容。The adapter uses these view references to bind each view to its content. RecyclerView 中的每一项都有一个关联的视图持有者实例,该实例将缓存该项的视图引用。Every item in the RecyclerView has an associated view holder instance that caches the view references for that item. 若要创建视图持有者,请使用以下步骤来定义一个类,以便保存每个项目的确切视图集:To create a view holder, use the following steps to define a class to hold the exact set of views per item:

  1. 子类 RecyclerView.ViewHolderSubclass RecyclerView.ViewHolder.
  2. 实现一个查找并存储视图引用的构造函数。Implement a constructor that looks up and stores the view references.
  3. 实现适配器可用于访问这些引用的属性。Implement properties that the adapter can use to access these references.

基本 RecyclerView 示例中提供了 ViewHolder 实现的详细示例。A detailed example of a ViewHolder implementation is presented in A Basic RecyclerView Example. 有关 RecyclerView.ViewHolder的详细信息,请参阅RecyclerView. ViewHolder 类引用For more information about RecyclerView.ViewHolder, see the RecyclerView.ViewHolder class reference.

适配器The Adapter

大多数 "RecyclerView" 集成代码在适配器中发生。Most of the "heavy-lifting" of the RecyclerView integration code takes place in the adapter. RecyclerView 要求你提供从 RecyclerView.Adapter 派生的适配器以访问数据源,并使用数据源中的内容填充每个项。RecyclerView requires that you provide an adapter derived from RecyclerView.Adapter to access your data source and populate each item with content from the data source. 由于数据源是特定于应用的,因此你必须实现可了解如何访问数据的适配器功能。Because the data source is app-specific, you must implement adapter functionality that understands how to access your data. 适配器从数据源中提取信息,并将其加载到 RecyclerView 集合中的每个项。The adapter extracts information from the data source and loads it into each item in the RecyclerView collection.

下图说明了适配器如何将数据源中的内容映射到 RecyclerView中每个行项内的各个视图:The following drawing illustrates how the adapter maps content in a data source through view holders to individual views within each row item in the RecyclerView:

说明将数据源连接到 ViewHolders 的适配器的关系图Diagram illustrating Adapter connecting Data Source to ViewHolders

适配器使用特定行项的数据加载每个 RecyclerView 行。The adapter loads each RecyclerView row with data for a particular row item. 例如,对于行位置p,适配器会在数据源中的位置p找到关联的数据,并将此数据复制到 RecyclerView 集合中位置p处的行项。For row position P, for example, the adapter locates the associated data at position P within the data source and copies this data to the row item at position P in the RecyclerView collection. 例如,在上面的绘图中,适配器使用视图持有者查找 ImageView 的引用并在该位置 TextView,因此当用户滚动集合并重复使用视图时,无需对这些视图重复调用 FindViewByIdIn the above drawing, for example, the adapter uses the view holder to lookup the references for the ImageView and TextView at that position so it doesn't have to repeatedly call FindViewById for those views as the user scrolls through the collection and reuses views.

实现适配器时,必须重写以下 RecyclerView.Adapter 方法:When you implement an adapter, you must override the following RecyclerView.Adapter methods:

  • OnCreateViewHolder – 实例化项布局文件和视图持有者。OnCreateViewHolder – Instantiates the item layout file and view holder.

  • OnBindViewHolder – 将位于指定位置的数据加载到其引用存储在给定视图持有者中的视图中。OnBindViewHolder – Loads the data at the specified position into the views whose references are stored in the given view holder.

  • ItemCount – 返回数据源中的项数。ItemCount – Returns the number of items in the data source.

布局管理器在 RecyclerView中定位项时调用这些方法。The layout manager calls these methods while it is positioning items within the RecyclerView.

向 RecyclerView 通知数据更改Notifying RecyclerView of Data Changes

RecyclerView 不会在其数据源的内容发生更改时自动更新其显示;当数据集发生变化时,适配器必须通知 RecyclerViewRecyclerView does not automatically update its display when the contents of its data source changes; the adapter must notify RecyclerView when there is a change in the data set. 数据集可以通过多种方式进行更改;例如,项目中的内容可能会更改,或者可能会更改数据的整体结构。The data set can change in many ways; for example, the contents within an item can change or the overall structure of the data may be altered. RecyclerView.Adapter 提供了许多方法,您可以调用这些方法以便 RecyclerView 以最有效的方式响应数据更改:RecyclerView.Adapter provides a number of methods that you can call so that RecyclerView responds to data changes in the most efficient manner:

  • NotifyItemChanged – 表明指定位置处的项已更改。NotifyItemChanged – Signals that the item at the specified position has changed.

  • NotifyItemRangeChanged – 表明指定位置范围内的项已更改。NotifyItemRangeChanged – Signals that the items in the specified range of positions have changed.

  • NotifyItemInserted – 表明指定位置中的项已新插入。NotifyItemInserted – Signals that the item in the specified position has been newly inserted.

  • NotifyItemRangeInserted – 表明指定位置范围内的项已新插入。NotifyItemRangeInserted – Signals that the items in the specified range of positions have been newly inserted.

  • NotifyItemRemoved – 表明指定位置中的项已被移除。NotifyItemRemoved – Signals that the item in the specified position has been removed.

  • NotifyItemRangeRemoved – 表明指定位置范围内的项已被移除。NotifyItemRangeRemoved – Signals that the items in the specified range of positions have been removed.

  • NotifyDataSetChanged – 表明数据集已更改(强制执行完全更新)。NotifyDataSetChanged – Signals that the data set has changed (forces a full update).

如果确切知道数据集的更改方式,则可以调用上述相应方法以最有效的方式刷新 RecyclerViewIf you know exactly how your data set has changed, you can call the appropriate methods above to refresh RecyclerView in the most efficient manner. 如果你不确切地知道数据集的更改方式,则可以调用 NotifyDataSetChanged,这种方法效率较低,因为 RecyclerView 必须刷新对用户可见的所有视图。If you do not know exactly how your data set has changed, you can call NotifyDataSetChanged, which is far less efficient because RecyclerView must refresh all the views that are visible to the user. 有关这些方法的详细信息,请参阅RecyclerViewFor more information about these methods, see RecyclerView.Adapter.

下一主题是一个基本的 RecyclerView 示例,它是一个示例应用程序,用于演示上述部分和功能的实际代码示例。In the next topic, A Basic RecyclerView Example, an example app is implemented to demonstrate real code examples of the parts and functionality outlined above.