ページング リストを表示する

このガイドはページング ライブラリの概要をベースとしており、情報のリストをアプリの UI に表示する方法について説明します。特に、情報が変更されたときの表示方法について詳しく説明します。

UI をビューモデルに接続する

次のコード スニペットに示すように、LiveData<PagedList> のインスタンスを PagedListAdapter に接続できます。

Kotlin

class ConcertActivity : AppCompatActivity() {
    private val adapter = ConcertAdapter()

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val viewModel: ConcertViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState);
        viewModel.concerts.observe(this, Observer { adapter.submitList(it) })
    }
}

Java

public class ConcertActivity extends AppCompatActivity {
    private ConcertAdapter adapter = new ConcertAdapter();
    private ConcertViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
        viewModel.concertList.observe(this, adapter::submitList);
    }
}

データソースから PagedList の新しいインスタンスが提供されると、アクティビティはこれらのオブジェクトをアダプターに送信します。PagedListAdapter の実装では、更新の計算方法を定義し、ページングとリストの差分を自動的に処理します。そのため、ViewHolder は提供された特定のアイテムにバインドするだけで済みます。

Kotlin

class ConcertAdapter() :
        PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) {
    override fun onBindViewHolder(holder: ConcertViewHolder, position: Int) {
        val concert: Concert? = getItem(position)

        // Note that "concert" is a placeholder if it's null.
        holder.bindTo(concert)
    }

    companion object {
        private val DIFF_CALLBACK = ... // See Implement the diffing callback section.
    }
}

Java

public class ConcertAdapter
        extends PagedListAdapter<Concert, ConcertViewHolder> {
    protected ConcertAdapter() {
        super(DIFF_CALLBACK);
    }

    @Override
    public void onBindViewHolder(@NonNull ConcertViewHolder holder,
            int position) {
        Concert concert = getItem(position);

        // Note that "concert" can be null if it's a placeholder.
        holder.bindTo(concert);
    }

    private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK
            = ... // See Implement the diffing callback section.
}

PagedListAdapter は、PagedList.Callback オブジェクトを使用してページ読み込みイベントを処理します。ユーザーがスクロールすると、PagedListAdapterPagedList.loadAround() を呼び出して、DataSource から取得する必要があるアイテムに関するヒントを基盤となる PagedList に提供します。

差分コールバックを実装する

次のサンプルは、関連するオブジェクト フィールドを比較する areContentsTheSame() の手動による実装を示しています。

Kotlin

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() {
    // The ID property identifies when items are the same.
    override fun areItemsTheSame(oldItem: Concert, newItem: Concert) =
            oldItem.id == newItem.id

    // If you use the "==" operator, make sure that the object implements
    // .equals(). Alternatively, write custom data comparison logic here.
    override fun areContentsTheSame(
            oldItem: Concert, newItem: Concert) = oldItem == newItem
}

Java

private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
        new DiffUtil.ItemCallback<Concert>() {

    @Override
    public boolean areItemsTheSame(Concert oldItem, Concert newItem) {
        // The ID property identifies when items are the same.
        return oldItem.getId() == newItem.getId();
    }

    @Override
    public boolean areContentsTheSame(Concert oldItem, Concert newItem) {
        // Don't use the "==" operator here. Either implement and use .equals(),
        // or write custom data comparison logic here.
        return oldItem.equals(newItem);
    }
};

アダプターには比較対象のアイテムの定義が含まれているため、新しい PagedList オブジェクトが読み込まれると、アダプターがそれらのアイテムの変更を自動的に検出します。その結果、RecyclerView オブジェクト内の有効なアイテム アニメーションがアダプターによってトリガーされます。

別のアダプター タイプを使用した差分の機能

PagedListAdapter から継承しない場合でも(独自のアダプターを提供するライブラリを使用する場合など)、AsyncPagedListDiffer オブジェクトを直接操作することにより、ページング ライブラリ アダプターの差分機能を使用できます。

UI にプレースホルダを表示する

アプリがデータの取得を完了する前に UI にリストを表示する必要がある場合は、プレースホルダのリストアイテムをユーザーに表示できます。PagedList は、データが読み込まれるまでリストアイテムのデータを null として表示することによって、こうしたケースに対処します。

プレースホルダには次のようなメリットがあります。

  • スクロールバーのサポート: PagedListPagedListAdapter にリストアイテムの数を提供します。アダプターはこの情報を使用して、フルサイズのリストを反映するスクロールバーを描画します。新しいページが読み込まれてもリストのサイズは変わらないため、スクロールバーが急に大きくなることはありません。
  • スピナーの読み込みが不要: リストのサイズは既知のため、追加の読み込みをユーザーに知らせる必要はありません。この情報はプレースホルダ自体から取得できます。

プレースホルダに対するサポートを追加する前に、次の前提条件を確認してください。

  • カウント可能なデータセットが必要: Room 永続ライブラリDataSource のインスタンスを使用することで、アイテムを効率的にカウントできます。ただし、カスタムのローカル ストレージ ソリューションまたはネットワークのみのデータ アーキテクチャを使用している場合は、コストが高くなる可能性があり、データセットを構成するアイテムの数を確認できなくなることもあります。
  • 読み込みが完了していないアイテムをアダプターで処理する必要がある: null のリストアイテムは、インフレーション用のリストの準備に使用するアダプターまたはプレゼンテーション メカニズムで処理する必要があります。たとえば、データを ViewHolder にバインドする場合は、読み込みが完了していないデータを表すデフォルト値を指定する必要があります。
  • 同じサイズのアイテムビューが必要: リストアイテムのサイズがその内容に基づいて変更される可能性がある場合(ソーシャル ネットワークの更新など)、アイテムのクロスフェードは見た目がよくありません。この場合、プレースホルダを無効にすることを強くおすすめします。

フィードバックを提供する

以下のリソースを通じてフィードバックやアイデアをお寄せください。

Issue Tracker
Google がバグを修正できるよう問題を報告します。

参考情報

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

サンプル

Codelab

動画