遷移至 Paging 3

Paging 3 與舊版 Paging 程式庫的差異很大。此版本提供強化功能,並解決了使用 Paging 2 的常見問題。如果您的應用程式已經使用舊版的 Paging 程式庫,請參閱本頁,進一步瞭解如何遷移至 Paging 3。

如果 Paging 3 是您在應用程式中採用的 Paging 程式庫的第一個版本,請參閱「載入及顯示分頁資料」,瞭解基本使用資訊。

遷移至 Paging 3 的好處

Paging 3 包含舊版本程式庫沒有的下列功能:

  • 優質的 Kotlin 協同程式和流程支援。
  • 支援使用 RxJava Single 或 Guava ListenableFuture 基元進行非同步載入。
  • 適用於回應式使用者介面設計的內建載入狀態和錯誤信號,包括重試和重新整理功能。
  • 改善存放區層,包括取消支援和簡化的資料來源介面。
  • 改善簡報層、清單分隔符、自訂頁面轉換以及載入狀態標頭和頁尾。

將您的應用程式遷移至 Paging 3

如要完全遷移至 Paging 3,您必須從 Paging 2 遷移這三個主要元件:

  • DataSource 類別
  • PagedList
  • PagedListAdapter

不過,部分 Paging 3 元件與舊版 Paging 回溯相容。特別是 Paging 3 的 PagingSource API 可以是舊版 LivePagedListBuilderRxPagedListBuilder 的資料來源。同樣地,Pager API 也可以搭配 asPagingSourceFactory() 方法使用舊版 DataSource 物件。這表示您有下列遷移選項:

  • 您可以將 DataSource 遷移至 PagingSource,但其他 Paging 導入程序保持不變。
  • 您可以遷移 PagedListPagedListAdapter,但仍使用舊版 DataSource API。
  • 您可以遷移整個 Paging 導入,將應用程式完全遷移至 Paging 3。

本頁各節將說明如何遷移應用程式各層的 Paging 元件。

DataSource 類別

本節說明將舊版 Paging 導入遷移至 PagingSource 的所有必要變更。

Paging 2 的 PageKeyedDataSourcePositionalDataSourceItemKeyedDataSource 全都會併入至 Paging 3 的 PagingSource API。系統會將所有舊 API 類別的載入方法合併為 PagingSource 中的單一 load() 方法。這樣可以減少程式碼重複的情形,因為用於導入舊版 API 類別之載入方法的許多邏輯經常相同。

系統會將所有載入方法參數在 Paging 3 中替換成 LoadParams 密封類別,其中包含每種載入類型的子類別。如果您需要區分 load() 方法中的載入類型,請檢查傳遞的 LoadParams 子類別為何:LoadParams.RefreshLoadParams.PrependLoadParams.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;
}

清單轉換

在舊版的 Paging 程式庫中,如要轉換分頁資料,必須使用下列方法:

  • DataSource.map()
  • DataSource.mapByPage()
  • DataSource.Factory.map()
  • DataSource.Factory.mapByPage()

在 Paging 3 中,所有轉換作業都會做為 PagingData 中的運算子。如果您使用上述清單中的任何方法來轉換分頁清單,在使用新的 PagingSource 建立 Pager 時,則必須將轉換邏輯從 DataSource 移至 PagingData

如要進一步瞭解如何使用 Paging 3 為分頁資料套用轉換,請參閱「轉換資料串流」。

PagedList

本節說明遷移舊版 Paging 導入的所有必要變更,以便在 Paging 3 中使用 PagerPagingData

PagedListBuilder 類別

PagingData 替換 Paging 2 中現有的 PagedList。如要遷移至 PagingData,您必須更新下列項目:

  • Paging 設定已從 PagedList.Config 移至 PagingConfig
  • LivePagedListBuilderRxPagedListBuilder 已合併為單一 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 取代為網路與資料庫分頁的處理常式。

如要進一步瞭解如何使用 RemoteMediator 在 Paging 3 中從網路和資料庫開啟頁面,請參閱 Android Paging 程式碼研究室

PagedListAdapter

本節說明遷移舊版 Paging 導入的所有必要變更,以使用 Paging 3 的 PagingDataAdapterAsyncPagingDataDiffer 類別。

Paging 3 會提供 PagingDataAdapter 來處理新的 PagingData 回應式串流。除此之外,PagedListAdapterPagingDataAdapter 擁有相同的介面。如要從 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 程式庫,請參閱以下資源:

程式碼研究室

範例