RecyclerViewで登場するキーワードについてのまとめ

あるデータセットをリスト形式で表示する場合、RecyclerViewウィジェットを使用して実装していく。 実装する上でいくつかのキーワードが登場するが、それぞれがどんな役割を果たしているのか頭の中でもやっとしている状態だったので、整理するためにも今回の記事に纏めたいと思う。

解説

Adapter

AndroidでいうAdapterはViewとデータセットを紐づける役割を持つ。 RecyclerView.Adapterを利用することで、表示するレイアウト(View)とデータセットを紐づける事ができる。 下記、公式引用。
Adapters provide a binding from an app-specific data set to views that are displayed within a RecyclerView.

LayoutInflater

LayoutInflaterを利用することで、XMLファイルに対応するViewオブジェクトをインスタンス化することができる。 よく、インフレートするという文章を見るが、前述したようにViewオブジェクトのインスタンス化という理解でいいのかなーと思う。

一例であるが下記の様にしてViewオブジェクトの生成を行うことができる。

val layoutInflater = LayoutInflater.from(context)
val view = layoutInflater.inflate(R.layout.sample_row, parent, false)

尚、Inflateには、一般的な意味として、膨らませるというような意味がある。

ViewHolder

RecyclerViewでのViewHolderの役割を一言で表すと「1行分のViewに対する参照を保持するもの」と言える。
Adapterは、画面に表示する行数分のViewHolderを作成し、行ごとに応じたデータをViewHolderに設定し、その情報をRecyclerViewに格納する。

RecyclerView.ViewHolder ⇒ 親Viewの参照を保持
RecyclerView.ViewHolderを継承した自作ViewHolder ⇒ 子Viewの参照を保持

RecyclerView.Adapterの基本的な実装

前述までの話を踏まえたうえで、RecyclerView.Adapterの実装のサンプルコードを下記に示す。

  • アダプター(SampleListAdapter.kt)
class SampleListAdapter(private val myDataset: MutableList<MyData>):
    RecyclerView.Adapter<SampleListAdapter.MyViewHolder>() {

    /* 基底クラスの初期化には親Viewへの参照を渡す */
    class MyViewHolder(view: View): RecyclerView.ViewHolder(view) {
    /* 子Viewへの参照を保持する */
        val imageView = view.findViewById(R.id.sample_imageView) as ImageView
        val textView = view.findViewById(R.id.sample_title_textView) as TextView
    }

    /* XMLレイアウトに応じたViewオブジェクトの作成とViewHolderの作成 */
    override fun onCreateViewHolder(parent: ViewGroup, position: Int): MyViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val view = layoutInflater.inflate(R.layout.sample_item_row, parent, false)

        return MyViewHolder(view)
    }

    /* 作成したViewHolder内のViewに対して更新を行う */
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        Picasso.get().load(url).into(holder.imageView)
        holder.textView.text = myDataset[position].text
    }

    override fun getItemCount(): Int = myDataset.size
}

フラグメント(SampleListFragment.kt)

class SampleListFragment: Fragment() {

    private lateinit var recyclerView: RecyclerView
    val dummyDataset: MutableList<MyData> = mutableListOf()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.sample_list_fragment, container, false)

        recyclerView = view.findViewById(R.id.recyclerview)
        val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
        recyclerView.layoutManager = layoutManager

        dummyData()
        val adapter = SampleListAdapter(dummyDataset)
        /* 作成したAdapterをRecyclerView.Adapterに接続 */
        recyclerView.adapter = adapter

        return view
    }
    
    fun dummyData() {
        val dummyData1 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText1")
        val dummyData2 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText2")
        val dummyData3 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText3")
        dummyDataset.add(dummyData1)
        dummyDataset.add(dummyData2)
        dummyDataset.add(dummyData3)

    }
}

まとめ

ざっと書いただけなので余り綺麗にまとまっていないが頭の中がだいぶ整理できた気がする。
RecyclerViewってListViewに比べると自分でいろいろ実装しないといけないところが増えているので、上記で書いたこと以外にも押さえておくべきところが沢山ある。
そこについては実装する機会があるときにまた纏めたいと思う。

参考サイト