Tatsuro のテックブログ

アプリ開発の技術情報を発信します。

【Android × Kotlin】RecyclerView に View Binding を導入する

以前、RecyclerView でリスト表示する方法を解説した際、RecyclerView の各項目のビューにアクセスする方法として findViewById を使用しました。しかし、View Binding を使用した方がビューに安全にアクセスすることができます。

よって、今回は RecyclerView の各項目のビューに View Binding でアクセスする方法を解説します。

なお、ここに掲載しているソースコードは以下の環境で動作確認しています。

  • Android Studio Chipmunk | 2021.2.1
  • JDK 11.0.12
  • Android Gradle Plugin 7.2.0
  • Kotlin 1.6.21
  • Gradle 7.4.2
  • androidx.recyclerview 1.2.1

build.gradle の変更

RecyclerView と View Binding を使用できるようにするために、build.gradle を変更します。

まず、View Binding を有効にするために、android ブロック内の buildFeaturesviewBindingtrue にします。

android {
    ︙
    buildFeatures {
        viewBinding = true
    }
}

そして、RecyclerView を使えるようにするために、dependencies ブロック内に次の依存関係を追加します。

dependencies {
    implementation "androidx.recyclerview:recyclerview:1.2.1"
}

以上で build.gradle の変更は完了です。これで、RecyclerView と View Binding を使用できるようになります。

View Binding の導入

実際に、RecyclerView に View Binding を導入します。RecyclerView の各項目のビューへのアクセスは RecyclerView のアダプタで行うので、前回の RecyclerView の解説で作成したソースコードをベースにして、TwoLinesListAdapter に View Binding を導入してみます。

TwoLinesListAdapter を以下のように実装します。

class TwoLinesListAdapter(
    private val twoLinesList: List<TwoLines>
) : RecyclerView.Adapter<TwoLinesListAdapter.ViewHolder>() {

    inner class ViewHolder(private val binding: TwoLinesItemBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(position: Int) {
            binding.apply {
                val twoLines = twoLinesList[position]
                primaryText.text = twoLines.primary
                secondaryText.text = twoLines.secondary
            }
        }
    }

    override fun onCreateViewHolder(
        parent: ViewGroup, viewType: Int
    ): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = TwoLinesItemBinding
            .inflate(inflater, parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(
        holder: ViewHolder, position: Int
    ) {
        holder.bind(position)
    }

    override fun getItemCount() = twoLinesList.size
}

ここで注目すべきは、ViewHolderonCreateViewHolderonBindViewHolder の 3 つです。

まず、ViewHolder を以下のように実装します。

    inner class ViewHolder(private val binding: TwoLinesItemBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(position: Int) {
            binding.apply {
                val twoLines = twoLinesList[position]
                primaryText.text = twoLines.primary
                secondaryText.text = twoLines.secondary
            }
        }
    }

ViewHolder は、RecyclerView の各項目のビューを保持するクラスです。

今回の View Binding の導入では、ViewHolder に View Binding のインスタンスを保持させます。そして、このインスタンスはコンストラクタから渡せるようにします。

また、ビューを更新する bind メソッドを実装します。RecyclerView がスクロールされるなどで onBindViewHolder が呼ばれるたびに、bind メソッドを使用してビューを更新します。

次に、onCreateViewHolder を以下のように実装します。

    override fun onCreateViewHolder(
        parent: ViewGroup, viewType: Int
    ): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = TwoLinesItemBinding
            .inflate(inflater, parent, false)
        return ViewHolder(binding)
    }

onCreateViewHolder では、ViewHolderインスタンスを生成して戻り値として返します。

ViewHolderインスタンスを生成するためには、View Binding のインスタンスを渡す必要があります。この View Binding のインスタンスを取得するために、TwoLinesItemBinding.inflate を使用します。

最後に、onBindViewHolder を以下のように実装します。

    override fun onBindViewHolder(
        holder: ViewHolder, position: Int
    ) {
        holder.bind(position)
    }

onBindViewHolder では、ViewHolder.bind を使用して、ビューホルダ内部のビューを更新します。

以上、View Binding の導入は完了です。これにより、View Binding にて RecyclerView の各項目のビューが更新されるようになります。

関連記事

RecyclerView でリスト表示する方法について、以下で解説しています。

tatsurotech.hatenablog.com