Paging 3 与早期版本的 Paging 库有很大不同。此版本提供了增强的功能,并解决了使用 Paging 2 时常见的困难。如果您的应用已使用早期版本的 Paging 库,请阅读此页面以详细了解如何迁移到 Paging 3。
如果 Paging 3 是您在应用中使用的第一个版本的 Paging 库,请参阅 加载和显示分页数据以获取基本用法信息。
迁移到 Paging 3 的好处
Paging 3 包括以下早期版本库中没有的功能
- 对 Kotlin 协程和 Flow 的一流支持。
- 支持使用 RxJava
Single
或 GuavaListenableFuture
原语进行异步加载。 - 内置的加载状态和错误信号,用于响应式 UI 设计,包括重试和刷新功能。
- 对存储库层的改进,包括取消支持和简化的数据源接口。
- 对表示层的改进,列表分隔符、自定义页面转换以及加载状态标题和页脚。
将您的应用迁移到 Paging 3
要完全迁移到 Paging 3,您必须迁移 Paging 2 的所有三个主要组件
DataSource
类PagedList
PagedListAdapter
但是,一些 Paging 3 组件与之前的 Paging 版本向后兼容。特别是,Paging 3 中的 PagingSource
API 可以作为 LivePagedListBuilder
和 RxPagedListBuilder
(来自旧版本)的数据源。类似地,Pager
API 可以使用旧的 DataSource
对象以及 asPagingSourceFactory()
方法。这意味着您有以下迁移选项
- 您可以将您的
DataSource
迁移到PagingSource
,但保留 Paging 实现的其余部分不变。 - 您可以迁移您的
PagedList
和PagedListAdapter
,但仍然使用旧的DataSource
API。 - 您可以迁移整个 Paging 实现,以完全将您的应用迁移到 Paging 3。
本页面中的各部分说明了如何在应用程序的各个层级上迁移分页组件。
数据源类
本部分描述了将旧的分页实现迁移到使用PagingSource
所需的全部更改。
分页 2 中的PageKeyedDataSource
、PositionalDataSource
和ItemKeyedDataSource
都已合并到分页 3 中的PagingSource
API 中。所有旧 API 类的加载方法都合并到PagingSource
中的单个load()
方法中。这减少了代码重复,因为旧 API 类实现中的加载方法之间的许多逻辑通常是相同的。
分页 3 中的所有加载方法参数都被替换为LoadParams
密封类,该类包含每个加载类型的子类。如果需要在load()
方法中区分加载类型,请检查传入的LoadParams
子类:LoadParams.Refresh
、LoadParams.Prepend
或LoadParams.Append
。
要了解有关实现PagingSource
的更多信息,请参阅定义数据源。
刷新键
PagingSource
的实现必须定义如何从已加载的分页数据中间恢复刷新。通过实现getRefreshKey()
来实现此目的,使用state.anchorPosition
作为最近访问的索引来映射正确的初始键。
Kotlin
// Replaces ItemKeyedDataSource. override fun getRefreshKey(state: PagingState): String? { return state.anchorPosition?.let { anchorPosition -> state.getClosestItemToPosition(anchorPosition)?.id } } // Replacing PositionalDataSource. override fun getRefreshKey(state: PagingState ): Int? { return state.anchorPosition }
Java
// Replaces ItemKeyedDataSource. @Nullable @Override String getRefreshKey(state: PagingState) { Integer anchorPosition = state.anchorPosition; if (anchorPosition == null) { return null; } return state.getClosestItemToPosition(anchorPosition); } // Replaces PositionalDataSource. @Nullable @Override Integer getRefreshKey(state: PagingState ) { return state.anchorPosition; }
Java
// Replacing ItemKeyedDataSource. @Nullable @Override String getRefreshKey(state: PagingState) { Integer anchorPosition = state.anchorPosition; if (anchorPosition == null) { return null; } return state.getClosestItemToPosition(anchorPosition); } // Replacing PositionalDataSource. @Nullable @Override Integer getRefreshKey(state: PagingState ) { return state.anchorPosition; }
列表转换
在旧版本的分页库中,分页数据的转换依赖于以下方法
DataSource.map()
DataSource.mapByPage()
DataSource.Factory.map()
DataSource.Factory.mapByPage()
在分页 3 中,所有转换都作为操作符应用于PagingData
。如果使用上述列表中的任何方法来转换分页列表,则必须将转换逻辑从DataSource
移动到PagingData
,并在使用新的PagingSource
构造Pager
时执行此操作。
要了解有关使用分页 3 对分页数据应用转换的更多信息,请参阅转换数据流。
PagedList
本部分描述了将旧的分页实现迁移到分页 3 中使用Pager
和PagingData
所需的全部更改。
PagedListBuilder 类
PagingData
取代了分页 2 中现有的PagedList
。要迁移到PagingData
,必须更新以下内容
- 分页配置已从
PagedList.Config
移动到PagingConfig
。 LivePagedListBuilder
和RxPagedListBuilder
已合并为单个Pager
类。Pager
通过其.flow
属性公开一个可观察的Flow<PagingData>
。RxJava 和 LiveData 变体也可用作扩展属性,这些属性可以通过静态方法从 Java 调用,并分别从paging-rxjava*
和paging-runtime
模块提供。
Kotlin
val flow = Pager( // Configure how data is loaded by passing additional properties to // PagingConfig, such as prefetchDistance. PagingConfig(pageSize = 20) ) { ExamplePagingSource(backend, query) }.flow .cachedIn(viewModelScope)
Java
// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact. CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel); Pager<Integer, User> pager = Pager<>( new PagingConfig(/* pageSize = */ 20), () -> ExamplePagingSource(backend, query)); Flowable<PagingData<User>> flowable = PagingRx.getFlowable(pager); PagingRx.cachedIn(flowable, viewModelScope);
Java
// CoroutineScope helper provided by the lifecycle-viewmodel-ktx artifact. CoroutineScope viewModelScope = ViewModelKt.getViewModelScope(viewModel); Pager<Integer, User> pager = Pager<>( new PagingConfig(/* pageSize = */ 20), () -> ExamplePagingSource(backend, query)); PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), viewModelScope);
要了解有关使用分页 3 设置PagingData
对象反应式流的更多信息,请参阅设置 PagingData 流。
分层源的 BoundaryCallback
在分页 3 中,RemoteMediator
取代了PagedList.BoundaryCallback
,作为从网络和数据库进行分页的处理程序。
要了解有关使用RemoteMediator
从分页 3 中的网络和数据库进行分页的更多信息,请参阅Android Paging codelab。
PagedListAdapter
本部分描述了将旧的分页实现迁移到使用分页 3 中的PagingDataAdapter
或AsyncPagingDataDiffer
类所需的全部更改。
分页 3 提供PagingDataAdapter
来处理新的PagingData
反应式流。否则,PagedListAdapter
和PagingDataAdapter
具有相同的接口。要从PagedListAdapter
迁移到PagingDataAdapter
,请将PagedListAdapter
的实现更改为改为扩展PagingDataAdapter
。
要了解有关PagingDataAdapter
的更多信息,请参阅定义 RecyclerView 适配器。
AsyncPagedListDiffer
如果当前使用具有AsyncPagedListDiffer
的自定义RecyclerView.Adapter
实现,请将实现迁移为改为使用分页 3 中提供的AsyncPagingDataDiffer
Kotlin
AsyncPagingDataDiffer(diffCallback, listUpdateCallback)
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
其他资源
要了解有关分页库的更多信息,请参阅以下其他资源