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。
此页面上的各节说明如何迁移应用每个层上的 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
上的操作符应用。如果使用上述列表中的任何方法来转换分页列表,则必须将转换逻辑从 DataSource
移动到 PagingData
,并在使用新的 PagingSource
构造 Pager
时进行。
要了解有关使用 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
如果当前使用带有 AsyncPagedListDiffer
的自定义 RecyclerView.Adapter
实现,请将实现迁移到改用 Paging 3 中提供的 AsyncPagingDataDiffer
。
Kotlin
AsyncPagingDataDiffer(diffCallback, listUpdateCallback)
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
Java
new AsyncPagingDataDiffer(diffCallback, listUpdateCallback);
其他资源
要了解有关 Paging 库的更多信息,请参阅以下其他资源