本指南基于 Paging 库概览,介绍了如何在应用界面中向用户显示信息列表,尤其是在此信息发生变化时。
将界面与视图模型关联
您可以将 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
对象来使用 Paging 库适配器的差异比较功能。
在界面中提供占位符
如果您希望界面在应用完成数据提取前显示列表,可以向用户显示占位符列表项。PagedList
对这种情况的处理方式是将列表项数据显示为 null
,直到加载了数据为止。
占位符具有以下优点:
- 支持滚动条:
PagedList
可向PagedListAdapter
提供列表项数量。此信息让适配器可以绘制滚动条来传达整个列表的大小。有新页面载入时,滚动条不会出现跳动,因为列表不会改变大小。 - 无需加载旋转图标:由于列表大小已知,因此无需提醒用户正在加载更多项。占位符本身会传达这一信息。
不过,在添加对占位符的支持之前,请注意以下前提条件:
- 需要可计数的数据集:Room 持久性库中的
DataSource
实例可以高效地计算项的数量。但如果您使用的是自定义本地存储解决方案或网络专用数据架构,确定数据集包含多少项可能会开销极大,甚至根本无法确定。 - 适配器必须考虑未加载的项:为准备列表以应对膨胀而使用的适配器或呈现机制需要处理 null 列表项。例如,将数据绑定到
ViewHolder
时,您需要提供默认值来表示未加载的数据。 - 需要同样大小的项视图:如果列表项大小会随着内容而变(例如社交网络更新),则项之间的交叉渐变效果并不理想。在这种情况下,我们强烈建议停用占位符。
提供反馈
通过以下资源与我们分享您的反馈和想法:
- 问题跟踪器
- 报告问题,以便我们修复 bug。
其他资源
如需详细了解 Paging 库,请参阅以下资源。
示例
Codelab
视频
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- Paging 2 库概览
- 迁移到 Paging 3
- 收集分页数据