Share via


RecyclerView のパーツと機能

RecyclerView は一部のタスク (ビューのスクロールやリサイクルなど) を内部で処理しますが、基本的には、コレクションを表示するためにヘルパー クラスを調整するマネージャーです。 RecyclerView は、タスクを次のヘルパー クラスに委任します。

  • Adapter – 項目レイアウトを拡張 (レイアウト ファイルの内容をインスタンス化) し、RecyclerView 内に表示されるビューにデータをバインドします。 アダプターは、項目クリック イベントも報告します。

  • LayoutManagerRecyclerView 内で項目ビューを測定して配置し、ビュー リサイクルのポリシーを管理します。

  • ViewHolder – ビュー参照を検索して保存します。 ビュー ホルダーは、項目ビューのクリックを検出するのにも役立ちます。

  • ItemDecoration – アプリが項目、ハイライト、視覚的なグループ境界間の区切り線を描画するために、特別な描画およびレイアウト オフセットを特定のビューに追加できるようにします。

  • ItemAnimator – 項目のアクション中、またはアダプターに対して変更が加えられた場合に実行されるアニメーションを定義します。

RecyclerViewLayoutManagerAdapter の各クラスの関係を次の図に示します。

Diagram of RecyclerView containing LayoutManager, using Adapter to access Data Set

この図が示すように、LayoutManager は、AdapterRecyclerView の間の仲介者として考えることができます。 LayoutManager は、RecyclerView に代わって Adapter メソッドを呼び出します。 たとえば、LayoutManager は、RecyclerView 内の特定の項目位置に新しいビューを作成するときに、Adapter メソッドを呼び出します。 Adapter は、その項目のレイアウトを拡張し、その位置にあるビューへの参照をキャッシュする ViewHolder インスタンス (表示されていません) を作成します。 LayoutManagerAdapter を呼び出して特定の項目をデータ セットにバインドすると、Adapter はその項目のデータを検索し、データ セットからそれを取得して、関連付けられている項目ビューにコピーします。

アプリで RecyclerView を使用する場合は、次のクラスの派生型を作成する必要があります。

  • RecyclerView.Adapter – アプリのデータ セット (アプリに固有) から、RecyclerView 内に表示される項目ビューへのバインドを提供します。 アダプターは、RecyclerView 内の各項目ビューの位置をデータ ソース内の特定の場所に関連付ける方法を認識します。 さらに、アダプターは個々の項目ビュー内のコンテンツのレイアウトを処理し、ビューごとにビュー ホルダーを作成します。 アダプターは、項目ビューによって検出された項目クリック イベントも報告します。

  • RecyclerView.ViewHolder – リソース検索が不必要に繰り返されないように、項目レイアウト ファイル内のビューへの参照をキャッシュします。 また、ビュー ホルダーは、ユーザーがビュー ホルダーに関連付けられた項目ビューをタップしたときに項目クリック イベントがアダプターに転送されるように配置します。

  • RecyclerView.LayoutManagerRecyclerView 内に項目を配置します。 いくつかの事前定義されたレイアウト マネージャーの 1 つを使用することも、独自のカスタム レイアウト マネージャーを実装することもできます。 RecyclerView はレイアウト ポリシーをレイアウト マネージャーに委任するため、アプリに大幅な変更を加えることなく、別のレイアウト マネージャーをプラグインできます。

また、必要に応じて次のクラスを拡張して、アプリ内の RecyclerView の外観を変更することもできます。

  • RecyclerView.ItemDecoration
  • RecyclerView.ItemAnimator

ItemDecorationItemAnimator を拡張しない場合、RecyclerView は既定の実装を使用します。 このガイドでは、ItemDecorationItemAnimator のカスタム クラスの作成方法については説明しません。これらのクラスの詳細については、「RecyclerView.ItemDecoration」と「RecyclerView.ItemAnimator」を参照してください。

ビューのリサイクルのしくみ

RecyclerView では、データ ソース内のすべての項目に項目ビューが割り当てられるわけではありません。 代わりに、画面に収まる数の項目ビューのみが割り当てられ、ユーザーがスクロールするときにそれらの項目レイアウトが再利用されます。 ビューが最初に画面外にスクロールすると、次の図に示すリサイクル プロセスが実行されます。

Diagram illustrating the six steps of view recycling

  1. ビューが画面外にスクロールして見えなくなると、"スクラップ ビュー" になります。

  2. スクラップ ビューはプールに配置され、"リサイクル ビュー" になります。 このプールは、同じ種類のデータを表示するビューのキャッシュです。

  3. 新しい項目が表示される場合、再利用のためにリサイクル プールからビューが取得されます。 このビューは、表示される前にアダプターによって再バインドされる必要があるため、"ダーティ ビュー" と呼ばれます。

  4. ダーティ ビューはリサイクルされます。アダプターは、表示する次の項目のデータを検索し、この項目のビューにこのデータをコピーします。 これらのビューの参照は、リサイクルされたビューに関連付けられているビュー ホルダーから取得されます。

  5. リサイクルされたビューは、これから画面上に表示される RecyclerView 内の項目のリストに追加されます。

  6. ユーザーが RecyclerView をリスト内の次の項目までスクロールすると、リサイクルされたビューが画面上に表示されます。 一方、別のビューが画面外にスクロールし、上記の手順に従ってリサイクルされます。

項目ビューの再利用に加えて、RecyclerView はもう 1 つの効率の最適化であるビュー ホルダーも使用します。 "ビュー ホルダー"は、ビュー参照をキャッシュする単純なクラスです。 アダプターが項目レイアウト ファイルを拡張するたびに、対応するビュー ホルダーも作成されます。 ビュー ホルダーは FindViewById を使用して、拡張された項目レイアウト ファイル内のビューへの参照を取得します。 これらの参照は、新しいデータを表示するためにレイアウトがリサイクルされるたびに新しいデータをビューに読み込むのに使用されます。

レイアウト マネージャー

レイアウト マネージャーは、RecyclerView 表示内での項目の配置を担当します。プレゼンテーションの種類 (リストまたはグリッド)、向き (項目が垂直方向または水平方向のどちらで表示されるか)、項目をどの向きで表示するか (通常の順序または逆の順序で) を決定します。 レイアウト マネージャーは、RecycleView 表示内の各項目のサイズと位置を計算する役割も担います。

レイアウト マネージャーには他にも目的があります。それは、ユーザーに表示されなくなった項目ビューをいつリサイクルするかについてのポリシーを決定することです。 レイアウト マネージャーはどのビューが表示されているか (どのビューが表示されていないか) を認識しているため、ビューをいつリサイクルできるかを決定するのに最適な立場にあります。 ビューをリサイクルするため、「ビューのリサイクルのしくみ」で前述したように、レイアウト マネージャーは通常、アダプターを呼び出して、リサイクルされたビューの内容を別のデータに置き換えます。

RecyclerView.LayoutManager を拡張して独自のレイアウト マネージャーを作成することも、事前定義されたレイアウト マネージャーを使用することもできます。 RecyclerView には、次の定義済みのレイアウト マネージャーが用意されています。

  • LinearLayoutManager – 垂直方向にスクロールできる列、または水平方向にスクロールできる行に項目を配置します。

  • GridLayoutManager – グリッドに項目を表示します。

  • StaggeredGridLayoutManager – 一部の項目の高さと幅が異なる、千鳥状のグリッドに項目を表示します。

レイアウト マネージャーを指定するには、選択したレイアウト マネージャーをインスタンス化し、それを SetLayoutManager メソッドに渡します。 レイアウト マネージャーを指定する "必要" があることに注意してください。RecyclerView では、既定で定義済みのレイアウト マネージャーは選択されません。

レイアウト マネージャーの詳細については、RecyclerView.LayoutManager クラスのリファレンスを参照してください。

ビュー ホルダー

ビュー ホルダーは、ビュー参照をキャッシュするために定義するクラスです。 アダプターはこれらのビュー参照を使用して、各ビューをそのコンテンツにバインドします。 RecyclerView 内のすべての項目には、その項目のビュー参照をキャッシュするビュー ホルダー インスタンスが関連付けられています。 ビュー ホルダーを作成するには、次の手順に従って、項目ごとに正確なビューのセットを保持するクラスを定義します。

  1. サブクラス RecyclerView.ViewHolder
  2. ビュー参照を検索して保存するコンストラクターを実装します。
  3. アダプターがこれらの参照にアクセスするために使用できるプロパティを実装します。

ViewHolder 実装の詳細な例は、「基本的な RecyclerView の例」に示されています。 RecyclerView.ViewHolder の詳細については、RecyclerView.ViewHolder クラスのリファレンスを参照してください。

アダプター

RecyclerView 統合コードの "重労働" のほとんどは、アダプターで行われます。 RecyclerView では、データ ソースにアクセスし、各項目にデータ ソースのコンテンツを設定するために、RecyclerView.Adapter から派生したアダプターを提供する必要があります。 データ ソースはアプリ固有であるため、データにアクセスする方法を理解するアダプター機能を実装する必要があります。 アダプターによってデータ ソースから情報が抽出され、それが RecyclerView コレクションの各項目に読み込まれます。

次の図は、アダプターがビュー ホルダーを介してデータ ソース内のコンテンツを RecyclerView の各行項目内の個々のビューにマップする方法を示しています。

Diagram illustrating Adapter connecting Data Source to ViewHolders

アダプターは RecyclerView の各行に特定の行項目のデーを読み込みます。 たとえば、行位置 P の場合、アダプターは、データ ソース内の位置 P に関連付けられているデータを検索し、RecyclerView コレクション内の位置 P にある行項目にこのデータをコピーします。 たとえば、上の図では、アダプターはビュー ホルダーを使用してその位置にある ImageViewTextView の参照を検索するため、ユーザーがコレクションをスクロールしてビューを再利用するときに、これらのビューに対して FindViewById を繰り返し呼び出す必要はありません。

アダプターを実装するときは、次の RecyclerView.Adapter メソッドをオーバーライドする必要があります。

  • OnCreateViewHolder – 項目レイアウト ファイルとビュー ホルダーをインスタンス化します。

  • OnBindViewHolder – 指定した位置にあるデータを、指定されたビュー ホルダーに参照が保存されているビューに読み込みます。

  • ItemCount – データ ソース内の項目の数を返します。

レイアウト マネージャーは、RecyclerView 内に項目を配置するときにこれらのメソッドを呼び出します。

RecyclerView へのデータ変更の通知

RecyclerView では、そのデータ ソースのコンテンツが変更されてもその表示は自動的には更新されません。データ セットに変更があった場合は、アダプターが RecyclerView に通知する必要があります。 データセットはさまざまな方法で変更される可能性があります。たとえば、項目内のコンテンツが変更されたり、データの全体的な構造が変更されたりする可能性があります。 RecyclerView.Adapter には、RecyclerView が最も効率的な方法でデータ変更に応答できるように呼び出すことができるメソッドが多数用意されています。

  • NotifyItemChanged – 指定した位置にある項目が変更されたことを通知します。

  • NotifyItemRangeChanged – 指定した位置範囲の項目が変更されたことを通知します。

  • NotifyItemInserted – 指定した位置の項目が新しく挿入されたことを通知します。

  • NotifyItemRangeInserted – 指定した位置範囲の項目が新しく挿入されたことを通知します。

  • NotifyItemRemoved – 指定した位置にある項目が削除されたことを通知します。

  • NotifyItemRangeRemoved – 指定した位置範囲の項目が削除されたことを通知します。

  • NotifyDataSetChanged – データ セットが変更されたことを通知します (完全な更新が強制されます)。

データ セットがどのように変更されたかを正確に把握している場合は、上記の適切なメソッドを呼び出して、最も効率的な方法で RecyclerView を更新できます。 データ セットがどのように変更されたかが正確にわからない場合は、NotifyDataSetChanged を呼び出すことができますが、RecyclerView はユーザーに表示されているすべてのビューを更新する必要があるため、効率が大幅に低下します。 これらのメソッドの詳細については、「RecyclerView.Adapter」を参照してください。

次のトピック「基本的な RecyclerView の例」では、上で概説したパーツと機能の実際のコード例を示すために、サンプル アプリを実装します。