Paging 3 に移行する

Paging 3 は、以前のバージョンのページング ライブラリとは大きく異なります。このバージョンでは拡張機能が提供されており、また Paging 2 でよく見られた問題点が解決されています。アプリで古いバージョンのページング ライブラリをすでに使用している場合は、このページを読み、Paging 3 への移行に関する詳細を確認してください。

アプリで初めて使用するページング ライブラリのバージョンが Paging 3 の場合は、ページング データの読み込みと表示で基本的な使用方法を確認してください。

Paging 3 に移行するメリット

Paging 3 では、旧バージョンのライブラリにはない以下の機能を利用できます。

  • Kotlin のコルーチンとフローの最高級のサポート。
  • RxJava Single または Guava ListenableFuture プリミティブを使用した非同期読み込みのサポート。
  • レスポンシブ UI 設計のための組み込みの読み込み状態およびエラー信号(再試行および更新機能を含む)。
  • リポジトリ レイヤの改善。キャンセルのサポートやシンプルなデータソース インターフェースなど。
  • プレゼンテーション層、リスト セパレータ、カスタムページ変換、読み込み状態のヘッダーとフッターの改善。

アプリを Paging 3 に移行する

Paging 3 に完全に移行するには、Paging 2 から 3 つの主要コンポーネントすべてを移行する必要があります。

  • DataSource クラス
  • PagedList
  • PagedListAdapter

ただし、Paging 3 コンポーネントの中には、以前のバージョンの Paging と下位互換性があるものもあります。たとえば、Paging 3 の PagingSource API は、古いバージョンの LivePagedListBuilderRxPagedListBuilder のデータソースにできます。また、Pager API で、asPagingSourceFactory() メソッドを使用して古い DataSource オブジェクトを使用することもできます。そのため、以下のような移行が可能です。

  • DataSourcePagingSource に移行して、残りの 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;
}

変換を一覧表示する

ページング ライブラリの旧バージョンでは、ページング データの変換は次のメソッドに依存しています。

  • 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 では、ネットワークおよびデータベースからのページングのハンドラとして、RemoteMediatorPagedList.BoundaryCallback に置き換わります。

RemoteMediator を使用して Paging 3 のネットワークとデータベースからページングする方法については、Android ページングの Codelab をご覧ください。

PagedListAdapter

このセクションでは、古い Paging の実装を移行して Paging 3 の PagingDataAdapter クラスと AsyncPagingDataDiffer クラスを使用するために必要なすべての変更について説明します。

Paging 3 には、新しい PagingData リアクティブ ストリームを処理する PagingDataAdapter が用意されています。それ以外の点では、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);

参考情報

ページング ライブラリについて詳しくは、以下の参考情報をご覧ください。

Codelab

サンプル