ページング リストの表示

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

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

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

Kotlin

    private val adapter = ConcertAdapter()
    private lateinit var viewModel: ConcertViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        viewModel = ViewModelProviders.of(this).get(ConcertViewModel::class.java)
        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 = ViewModelProviders.of(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.
    }
    

PagedListAdapterPagedList.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 にバインドする場合、読み込みが完了していないデータを表示するためにデフォルト値を指定する必要があります。
  • 同じサイズのアイテムビューが必要: リストアイテムのサイズがその内容に基づいて変更される可能性がある場合(ソーシャル ネットワークの更新など)、アイテムのクロスフェードは見た目がよくありません。この場合、プレースホルダを無効にすることを強くおすすめします。

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

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

公開バグトラッカー
Google がバグを修正できるよう問題を報告します。

参考情報

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

サンプル

コードラボ

動画