遷移至 Paging 3

Paging 3 與舊版 Paging 程式庫的差異很大。這個版本提供強化功能,一流的 Kotlin 協同程式和 Flow 支援,以及與 Jetpack Compose 的完美整合。

遷移至 Paging 3 的好處

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

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

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

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

  • DataSource 類別
  • PagedList
  • 簡報層 (至 LazyPagingItems)

不過,部分 Paging 3 元件與舊版 Paging 回溯相容。特別是 Pager API 可以搭配 asPagingSourceFactory 方法使用舊版 DataSource 物件。這表示您有下列遷移選項:

  • 您可以將 DataSource 遷移至 PagingSource,但其他 Paging 導入程序保持不變。
  • 您可以遷移整個 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 做為最新存取的索引,以對應正確的初始金鑰。

// 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
}

清單轉換

在舊版的 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
  • 舊版建構工具類別已合併為單一 Pager 類別。
  • Pager 會以 .flow 屬性顯示可觀測的 Flow<PagingData>
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)

如要進一步瞭解如何使用 Paging 3 設定 PagingData 物件的回應式串流,請參閱「設定 PagingData 串流」。

BoundaryCallback 分層來源

在 Paging 3 中,RemoteMediator 會將 PagedList.BoundaryCallback 取代為網路與資料庫分頁的處理常式。

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

LazyPagingItems

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

Paging 3 會提供 collectAsLazyPagingItems 來處理新的 PagingData 流程。如要遷移簡報層,請使用 paging-compose 構件和 collectAsLazyPagingItems 收集 PagingData 項目,並在 @Composable 函式中顯示這些項目。

如要進一步瞭解 LazyPagingItems,請參閱「載入並顯示分頁資料」。

清單差異和更新

如果您目前使用自訂清單差異邏輯,請改為遷移導入以使用 Paging 3 提供的 LazyPagingItems。如要確保差異發生在正確位置,請在延遲載入清單中指定項目鍵:

@Composable
fun UserScreen(viewModel: UserViewModel) {
    // Collects the Flow into a LazyPagingItems object
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserList(lazyPagingItems: LazyPagingItems<User>) {
    LazyColumn {
        items(
            count = lazyPagingItems.itemCount,
            // Provide a stable key for each item, similar to DiffUtil in Views
            key = lazyPagingItems.itemKey { user -> user.id } 
        ) { index ->
            val user = lazyPagingItems[index]
            if (user != null) {
                UserRow(user = user)
            }
        }
    }
}

如要進一步瞭解項目鍵,請參閱「項目鍵」。

載入狀態

在 Paging 3 中,您不需要使用個別的介面卡,即可顯示載入狀態的標頭或頁尾。LazyPagingItems 物件會公開 loadState 屬性,您可以在 LazyColumn 中直接檢查。

LazyColumn {
    // ... items(lazyPagingItems) go here ...

    // Show loading spinner at bottom of list when appending data
    if (lazyPagingItems.loadState.append is LoadState.Loading) {
        item {
            CircularProgressIndicator(modifier = Modifier.fillMaxWidth())
        }
    }
}

其他資源

如要進一步瞭解 Paging 程式庫,請參閱以下資源:

說明文件

Views content