Paging 3 与旧版 Paging 库存在很大区别。此版本提供了增强型功能,还解决了使用 Paging 2 时常见的问题。如果您的应用已在使用旧版 Paging 库,请阅读本页面,详细了解如何迁移到 Paging 3。
如果 Paging 3 是您在应用中使用的第一个 Paging 库版本,请参阅加载并显示分页数据,了解基本用法信息。
迁移到 Paging 3 的优势
Paging 3 包含旧版库中没有的下列功能:
- 为 Kotlin 协程和流程提供一流的支持。
- 支持使用 RxJava
Single
或 GuavaListenableFuture
基元进行异步加载。 - 针对自适应界面设计的内置加载状态和错误信号,包括重试和刷新功能。
- 改进了代码库层,包括取消支持和简化的数据源界面。
- 改进了表示层、列表分隔符、自定义页面转换和加载状态页眉和页脚。
将应用迁移到 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。
本页中的各个部分介绍了如何迁移应用每个层上的 Paging 组件。
DataSource 类
本部分介绍迁移旧版 Paging 实现以使用 PagingSource
所需的所有更改。
Paging 2 中的 PageKeyedDataSource
、PositionalDataSource
和 ItemKeyedDataSource
都合并到了 Paging 3 中的 PagingSource
API 中。所有旧版 API 类中的加载方法都合并到了 PagingSource
中的单个 load()
方法中。这样可以减少代码重复,因为在旧版 API 类的实现中,各种加载方法之间的很多逻辑通常是相同的。
在 Paging 3 中,所有加载方法参数被一个 LoadParams
密封类替代,该类中包含了每个加载类型所对应的子类。如果需要区分 load()
方法中的加载类型,请检查传入了 LoadParams
的哪个子类:LoadParams.Refresh
、LoadParams.Prepend
还是 LoadParams.Append
。
如需详细了解如何实现 PagingSource
,请参阅定义数据源。
刷新键
PagingSource
实现必须定义如何从已加载分页数据的中间恢复刷新。为此,您可以实现 getRefreshKey()
,以使用 state.anchorPosition
作为最近访问的索引来映射正确的初始键。
Kotlin
// Replaces ItemKeyedDataSource. override fun getRefreshKey(state: PagingState<String, User>): String? { return state.anchorPosition?.let { anchorPosition -> state.getClosestItemToPosition(anchorPosition)?.id } } // Replacing PositionalDataSource. override fun getRefreshKey(state: PagingState<Int, User>): Int? { return state.anchorPosition }
Java
// Replaces ItemKeyedDataSource. @Nullable @Override String getRefreshKey(state: PagingState<String, User>) { Integer anchorPosition = state.anchorPosition; if (anchorPosition == null) { return null; } return state.getClosestItemToPosition(anchorPosition); } // Replaces PositionalDataSource. @Nullable @Override Integer getRefreshKey(state: PagingState<Integer, User>) { return state.anchorPosition; }
Java
// Replacing ItemKeyedDataSource. @Nullable @Override String getRefreshKey(state: PagingState<String, User>) { Integer anchorPosition = state.anchorPosition; if (anchorPosition == null) { return null; } return state.getClosestItemToPosition(anchorPosition); } // Replacing PositionalDataSource. @Nullable @Override Integer getRefreshKey(state: PagingState<Integer, User>) { return state.anchorPosition; }
列表转换
在旧版 Paging 库中,分页数据的转换依赖于以下方法:
DataSource.map()
DataSource.mapByPage()
DataSource.Factory.map()
DataSource.Factory.mapByPage()
在 Paging 3 中,所有转换都作为运算符应用于 PagingData
。如果使用上述列表中的某个方法转换分页列表,则在使用新的 PagingSource
构建 Pager
时,必须将转换逻辑从 DataSource
变为 PagingData
。
如需详细了解如何使用 Paging 3 转换分页数据,请参阅转换数据流。
PagedList
本部分介绍迁移旧版 Paging 实现以使用 Paging 3 中的 Pager
和 PagingData
所需的所有更改。
PagedListBuilder 类
PagingData
替换了 Paging 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);
如需详细了解如何使用 Paging 3 设置 PagingData
对象的响应式流,请参阅设置 PagingData 流。
分层源的 BoundaryCallback
在 Paging 3 中,RemoteMediator
取代 PagedList.BoundaryCallback
作为处理从网络和数据库分页的处理程序。
如需详细了解如何在 Paging 3 中使用 RemoteMediator
从网络和数据库分页,请参阅 Android Paging Codelab。
PagedListAdapter
本部分介绍迁移旧版 Paging 实现以使用 Paging 3 中的 PagingDataAdapter
或 AsyncPagingDataDiffer
类所需的所有更改。
Paging 3 提供 PagingDataAdapter
来处理新的 PagingData
响应式流。否则,PagedListAdapter
和 PagingDataAdapter
将具有相同的接口。如需从 PagedListAdapter
迁移到 PagingDataAdapter
,请更改 PagedListAdapter
的实现,以扩展 PagingDataAdapter
。
如需详细了解 PagingDataAdapter
,请参阅定义 RecyclerView 适配器。
AsyncPagedListDiffer
如果您目前将自定义 RecyclerView.Adapter
实现与 AsyncPagedListDiffer
搭配使用,请迁移您的实现以使用 Paging 3 中提供的 AsyncPagingDataDiffer
:
Kotlin
AsyncPagingDataDiffer(diffCallback, listUpdateCallback)
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
其他资源
如需详细了解 Paging 库,请参阅下列其他资源: