Google 致力于为黑人社区推动种族平等。查看具体举措

显示分页列表

本指南基于分页库概览,介绍了如何在应用界面中向用户显示信息列表,尤其是在此信息发生变化时。

将界面与视图模型关联

您可以将 LiveData<PagedList> 的实例连接到 PagedListAdapter,如以下代码段所示:

Kotlin

    class ConcertActivity : AppCompatActivity() {
        private val adapter = ConcertAdapter()

        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        private val viewModel: ConcertViewModel by viewModels()

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState);
            viewModel.concerts.observe(this, Observer { adapter.submitList(it) })
        }
    }
    

Java

    public class ConcertActivity extends AppCompatActivity {
        private ConcertAdapter adapter = new ConcertAdapter();
        private ConcertViewModel viewModel;

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
            viewModel.concertList.observe(this, adapter::submitList);
        }
    }
    

当数据源提供 PagedList 的新实例时,Activity 会将这些对象发送到适配器。PagedListAdapter 实现定义了更新的计算方式,并自动处理分页和列表差异。因此,您的 ViewHolder 只需要绑定到提供的特定项即可:

Kotlin

    class ConcertAdapter() :
            PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) {
        override fun onBindViewHolder(holder: ConcertViewHolder, position: Int) {
            val concert: Concert? = getItem(position)

            // Note that "concert" is a placeholder if it's null.
            holder.bindTo(concert)
        }

        companion object {
            private val DIFF_CALLBACK = ... // See Implement the diffing callback section.
        }
    }
    

Java

    public class ConcertAdapter
            extends PagedListAdapter<Concert, ConcertViewHolder> {
        protected ConcertAdapter() {
            super(DIFF_CALLBACK);
        }

        @Override
        public void onBindViewHolder(@NonNull ConcertViewHolder holder,
                int position) {
            Concert concert = getItem(position);

            // Note that "concert" can be null if it's a placeholder.
            holder.bindTo(concert);
        }

        private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK
                = ... // See Implement the diffing callback section.
    }
    

PagedListAdapter 使用 PagedList.Callback 对象处理网页加载事件。当用户滚动时,PagedListAdapter 会调用 PagedList.loadAround() 来向底层 PagedList 提供关于应从 DataSource 获取哪些项的提示。

实现差异回调

以下示例展示了用于比较相关对象字段的 areContentsTheSame() 的手动实现:

Kotlin

    private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() {
        // The ID property identifies when items are the same.
        override fun areItemsTheSame(oldItem: Concert, newItem: Concert) =
                oldItem.id == newItem.id

        // If you use the "==" operator, make sure that the object implements
        // .equals(). Alternatively, write custom data comparison logic here.
        override fun areContentsTheSame(
                oldItem: Concert, newItem: Concert) = oldItem == newItem
    }
    

Java

    private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
            new DiffUtil.ItemCallback<Concert>() {

        @Override
        public boolean areItemsTheSame(Concert oldItem, Concert newItem) {
            // The ID property identifies when items are the same.
            return oldItem.getId() == newItem.getId();
        }

        @Override
        public boolean areContentsTheSame(Concert oldItem, Concert newItem) {
            // Don't use the "==" operator here. Either implement and use .equals(),
            // or write custom data comparison logic here.
            return oldItem.equals(newItem);
        }
    };
    

由于适配器包含比较项的定义,因此适配器会在有新的 PagedList 对象加载时自动检测这些项的更改。这样,适配器就会在您的 RecyclerView 对象内触发有效的项目动画。

使用其他适配器类型实现差异化功能

如果您选择不从 PagedListAdapter 继承(例如,当您使用的库提供自己的适配器时),仍可以直接通过 AsyncPagedListDiffer 对象来使用分页库适配器的差异化功能。

在界面中提供占位符

如果您希望界面在应用完成数据获取前显示列表,可以向用户显示占位符列表项。PagedList 对这种情况的处理方式是将列表项数据显示为 null,直到加载了数据为止。

占位符具有以下优点:

  • 支持滚动条PagedList 可向 PagedListAdapter 提供列表项数量。此信息允许适配器绘制滚动条来传达整个列表大小。有新页面载入时,滚动条不会跳到指定位置,因为列表不会改变大小。
  • 无需加载旋转图标:由于列表大小已知,因此无需提醒用户正在加载更多项。占位符本身会传达这一信息。

不过,在添加对占位符的支持之前,请注意以下前提条件:

  • 需要可计数的数据集Room 持久性库 中的 DataSource 实例可以有效地计算项的数量。但如果您使用的是自定义本地存储解决方案或网络专用数据架构,确定数据集包含多少项可能会开销极大,甚至根本无法确定。
  • 适配器必须考虑未加载的项:为准备列表以应对增长而使用的适配器或呈现机制需要处理 Null 列表项。例如,将数据绑定到 ViewHolder 时,您需要提供默认值来表示未加载数据。
  • 需要同样大小的项视图:如果列表项大小会随着内容而变(例如社交网络更新),则项之间的交叉渐变效果并不理想。在这种情况下,我们强烈建议停用占位符。

提供反馈

通过以下资源与我们分享您的反馈和想法:

问题跟踪器
报告问题,以便我们可以修复错误。

其他资源

要详细了解分页库,请参阅以下资源。

示例

Codelab

视频