本指南以 分页库概述 为基础,介绍如何向用户展示应用 UI 中的信息列表,尤其是在信息发生变化时。
将 UI 连接到视图模型
您可以将 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
的新实例时,活动会将这些对象发送到适配器。 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
对象来使用 Paging 库适配器的差异化功能。
在你的 UI 中提供占位符
在你想让你的 UI 在应用程序完成数据获取之前显示列表的情况下,你可以向用户显示占位符列表项。 PagedList
通过将列表项数据呈现为 null
来处理这种情况,直到数据加载完毕。
占位符具有以下优势
- 支持滚动条:
PagedList
将列表项的数量提供给PagedListAdapter
。此信息允许适配器绘制一个滚动条,以传达列表的完整大小。随着新页面的加载,滚动条不会跳动,因为你的列表不会改变大小。 - 无需加载旋转器: 由于列表大小已知,因此无需提醒用户正在加载更多项目。占位符本身就传达了这一信息。
但在添加对占位符的支持之前,请牢记以下先决条件
- 需要可计数的数据集: 来自 Room 持久化库 的
DataSource
实例可以有效地计算其项目。但是,如果你使用的是自定义本地存储解决方案或 仅网络数据架构,则确定你的数据集包含多少项目可能很昂贵,甚至不可能。 - 需要适配器来处理未加载的项目: 你用来准备要填充的列表的适配器或表示机制需要处理 null 列表项。例如,当你将数据绑定到
ViewHolder
时,你需要提供默认值来表示未加载的数据。 - 需要相同大小的项目视图: 如果列表项大小可以根据其内容而改变,例如社交网络更新,那么项目之间的交叉淡入淡出效果看起来不好。我们强烈建议在这种情况下禁用占位符。
提供反馈
通过以下资源与我们分享您的反馈和想法
- 问题跟踪器
- 报告问题,以便我们能够修复错误。
其他资源
要了解更多关于 Paging 库的信息,请参阅以下资源。
示例
Codelabs
视频
推荐给你
- 注意:当 JavaScript 关闭时,链接文本将显示
- 分页 2 库概述
- 迁移到 Paging 3
- 收集分页数据