【Android開発】RecyclerViewの使い方

book プログラミング

Androidのアプリ開発で大量のデータを画面上に表示したいときがあります。

recycler-view-layout
参照:RecyclerViewの基礎 Codelab

RecyclerViewを使えば、大量のデータを効率的に表示することができます。

RecyclerViewは、優れたアプリを作るためのライブラリ「Android Jetpack」の1つです。

RecyclerViewとは

Androidデベロッパーでは、RecyclerViewは次のように説明されています。

RecyclerView は、その名のとおり、これらの個々の要素をリサイクルします。アイテムが画面外にスクロールされても、RecyclerView はビューを破棄せず、画面上にスクロールされた新しいアイテムのビューを再利用します。この再利用は、パフォーマンスの大幅な改善、アプリの応答性の向上、消費電力の削減をもたらします。

Androidデベロッパー

Androidでデータをリストやグリッド状に表示させるには、RecyclerView以外にもListViewやGridViewがあります。

RecyclerViewは、ListViewやGridViewに比べて実装が複雑になりますが、様々な方法でデータを表示させることができ、現在の画面上に表示されているデータしか処理しないため、非常に効率的です。

RecyclerViewを使えば、画面からスクロールアウトしたビューを再利用して新しいデータを表示します。以下の画像では、ABCのビューがスクロールアウトした後に、新しいデータのXYZを表示するためにABCのビューを再利用します。

recycler-view-concept
参照:RecyclerViewの基礎 Codelab

RecyclerViewを使うための5つのステップ

今回はデータをリスト表示する、以下のようなアプリを作成します。

video-recycler-view

RecyclerViewを使うために、大きく5つ作業が必要になります。

  1. gradleに依存関係を追加する
  2. レイアウトにrecyclerViewを配置する
  3. データ1つあたりのレイアウトファイルを作成する
  4. アダプターとビューホルダーを作成する
  5. レイアウトマネージャーを作成する

それでは1つずつ見ていきましょう。

ステップ1 gradleに依存関係を追加する

「build.gradle(Module: app)」ファイルを開いて、次の依存関係を追加します。

dependencies {
    ・・・
    implementation 'androidx.recyclerview:recyclerview:1.2.1'
}

最新のバージョンは、AndroidXのリリースページで確認することができます。

ステップ2 レイアウトにrecyclerViewを配置する

レイアウトにRecyclerViewを配置します。

res/layoutの「activity_main.xml」を開いて、以下の内容に書き換えます。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
    
</LinearLayout>

<androidx.recyclerview.widget.RecyclerView />の部分にデータが表示されるようになります。 

ステップ3 データ1つあたりのレイアウトファイルを作成する

RecyclerViewで表示するデータ1つあたりのレイアウトファイルを作成します。

res/layoutフォルダを右クリックし、「New」→「XML」→「Layout XML File」からレイアウトファイルを作成します。

今回は、「text_item_view」という名前で作成します。「text_item_view.xml」を開いたら以下のように変更してください。

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView"
    android:textSize="48sp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

TextViewだけのシンプルなレイアウトファイルです。TextView1つだけでなく、複数のビューを配することもできます。

ステップ4 アダプターとビューホルダーを作成する

RecyclerViewを使用するためには、アダプターとビューホルダーが必要になります。

このアダプターの作成がRecyclerViewの中心的な作業になります。

アダプターとは

アダプターとは、「適合させる」という意味があります。アダプターパターンは、有名なGoFのデザインパターンの一つで、あるクラスのインターフェースを変更することなく別クラスのインターフェースに変更します。

例えば、電気のコンセントは日本と海外では異なります。日本の家電を海外で使うときは、変換アダプターを使いプラグの形状を変えて使います。

adapter-image

このように家電自体のコンセントを変えずに、別のコンセントで使えるようにするのがアダプター役割です。

アダプターパターンも電気のコンセントと同じように、異なるクラス同士のインターフェースを変更せずに使用する役割を担います。

今回のコードでは、表示するデータをレイアウトファイルのRecyclerViewに表示させるためにアダプターを使っています。

RecyclerViewでアダプター使うときには、次の3つのメソッドをオーバーライドする必要があります。

  • onCreateViewHolder():RecyclerViewは、新しいViewHolderを作成する必要があるたびにこのメソッドを呼び出します。
  • onBindViewHolder():RecyclerViewは、このメソッドでViewHolderにデータを関連付けます。
  • getItemCount():RecyclerViewは、このメソッドで表示するデータの数を取得します。

RecyclerViewでデータが表示されるまでの流れを簡単に説明すると次のとおりです。

  1. onCreateViewHolder()を呼び出す
  2. onCreateViewHolder()で、アイテムのレイアウトXMLファイルをもとにビューホルダーを作成して返す。
  3. onBindviewHolder()を呼び出す。そのときに、2で作成したビューホルダーと表示される位置を受け取る。
  4. 受け取ったビューホルダーに表示するデータを埋め込む

アダプタークラスの作成

アダプターが何かわかったところで、実際のコードを作成してみましょう。

javaフォルダ内のプロジェクトを右クリックし、「New」→「Kotlin Class/File」からKotlinファイルを作成します。

「ItemAdapter」という名前で作成し、「ItemAdapter.kt」を開いたら以下のように変更してください。Import文などは省略しています。

class ItemAdapter: RecyclerView.Adapter<ItemAdapter.ViewHolder>() {

    val data = listOf<Int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

    class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
        val textView: TextView
        init {
            textView = view.findViewById(R.id.textView)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val view = layoutInflater.inflate(R.layout.text_item_view, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        val item = data[position]
        viewHolder.textView.text = item.toString()
    }
    
    override fun getItemCount() = data.size
}
onCreateViewHolder()

onCreateViewHolder()は、新しいビューホルダーを作成する必要があるときに呼び出され、ビューホルダーを返します。つまり、表示するためのビューホルダーを作成します。

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val layoutInflater = LayoutInflater.from(parent.context)
    val view = layoutInflater.inflate(R.layout.text_item_view, parent, false)
    return ViewHolder(view)
}

ビューホルダーを作成するのですが、その前にビューを作成する必要があります。

xmlファイルからビューを作成するために使うのがInflate()です。inflateは「膨らます」という意味で、xmlファイルのレイアウトを膨らませて画面に表示させるイメージです。

レイアウトのビューを作成するためにLayoutInflaterを使います。LayoutInflater.from()メソッドに対象となるコンテキストを渡して、膨らませるLayoutInflaterを取得します。

そして、inflate()にステップ3で作成した「text_item_view.xml」を渡し、ビューを作ります。

最後にビューホルダーを作成して返しますが、ビューホルダーはアダプタークラスのサブクラスで定義しています。

class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
    val textView: TextView
    init {
        textView = view.findViewById(R.id.textView)
    }
}

この時点では実際のデータは埋め込められていません。実際のデータを埋め込むのが、次に説明するonBindViewHolder()です。

onBindViewHolder()

onBindViewHolder()は、ViewHolderに表示するデータを関連付けます。ビューホルダーに指定された位置のデータを埋め込むために使います。

引数として、onCreateViewHolder()で作成したビューホルダーとビューに表示するデータの位置を受け取ります。

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
    val item = data[position]
    viewHolder.textView.text = item.toString()
}

つまりonBindViewHolder()は、表示するデータ1つを取得して、そのデータをビューホルダーに埋め込んでいます。

//表示する1つのデータ
val item = data[position]

//ビューホルダーのtextに文字列として埋め込む
viewHolder.textView.text = item.toString()
getItemCount()

getItemCount()は、表示するためのデータの数を取得します。表示するデータは、1から20までの数字を格納したリストデータになります。

RecyclerViewは、アダプターが持っているデータの数を知る必要があり、この情報で表示するデータが他にないかを判断します。

//表示するためのデータ
val data = listOf<Int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

override fun getItemCount() = data.size  //dataのサイズ この場合は20

ステップ5 レイアウトマネージャーを作成する

RecyclerViewに必要なアダプターなどの作成はできました。あとは、RecyclerViewに設定していきます。

「MainActivity.kt」を開いて、次のコードを記載します。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //RecyclerViewの取得
        val recyclerView = findViewById<RecyclerView>(R.id.rvList)

        //Adapterの設定
        val adapter = ItemAdapter()
        recyclerView.adapter = adapter

        //LayoutManagerの設定
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
    }
}

まず、ステップ2で作成した「activity_main.xml」のRecyclerViewを取得します。そして、RecyclerViewにアダプターとレイアウトマネージャーを設定します。

レイアウトマネージャーとは

1つ1つのデータをどのような並びで表示させるかを決めるのがレイアウトマネージャーです。

RecyclerViewは、LayoutManagerを使用してリストやグリッドなどの表示を行います。

レイアウトマネージャーは、標準で3つのレイアウトが用意されています。

  • LinearLayoutManager:リストで表示する
  • GridLayoutManager:それぞれのデータの高さ(幅)がそろった格子状に表示する
  • StaggeredGridLayoutManager:格子状に表示するが、高さ(幅)がそれぞれのデータで異なる。

レイアウトマネージャーを指定しているのが以下のコードです。リスト表示するため、LinearLayoutManagerを指定しています。

val layouManager = LinearLayoutManager(this)

LinearLayoutManagerは、リストは縦に並んで表示されます。

表示するリストを横に並べさせることもできます。その場合は引数に「LinearLayoutManager.HORIZONTAL」を渡します。

val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recycler-view-horizontal

ちなみに、3番目の引数はレイアウトを逆に表示するかどうかです。「true」を指定した場合は、下から上(横並びのときは右から左)に並べられたリストになります。

val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)
recycler-view-reverse

LinearLayoutManager以外の場合は、次のように指定します。

//5列の格子状に表示
val layouManager = GridLayoutManager(this, 5)

//5列で高さがバラバラな格子状に表示
val layoutManager = StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL)
recycler-view-grid

今回の場合は、表示するデータの高さがすべて同じなので、GridLayoutManagerもStaggeredGridLayoutManagerも同じような表示になります。

まとめ

RecyclerViewは、実装が少し難しいがデータを効率的にリストやグリッド状に表示させることができる。

RecyclerViewを使うために、大きく5つ作業が必要になる。

  1. gradleに依存関係を追加する
  2. レイアウトにrecyclerViewを配置する
  3. データ1つあたりのレイアウトファイルの作成する
  4. アダプターとビューホルダーを作成する
  5. レイアウトマネージャーを作成する

Android開発のためのオススメ書籍

設計についてのオススメの書籍

Android アプリ設計パターン入門

Android アプリ設計パターン入門

  • 著者: 日高 正博,小西裕介,藤原聖,吉岡 毅,今井 智章,
  • 製本版,電子版
  • PEAKSで購入する

参考サイト

RecyclerViewで動的リストを作成する Androidデベロッパー

RecyclerViewの基礎 Codelab

LinearLayoutManager Androidデベロッパー

GridLayoutManager Androidデベロッパー

StaggeredGridLayoutManager Androidデベロッパー

タイトルとURLをコピーしました