Android Kotlin基礎講座 07.2:DiffUtilとRecycleViewのデータバインディング

タスク:RecyclerViewにDataBindingを使う

このタスクでは、前回の記事で使われた技術と同じ技術を用いてデータバインディングをセットアップします。またfindViewById()の呼び出しを排除していきます。

ステップ1:レイアウトファイルにデータバインディングを追加する

  1. list_item_sleep_night.xmlレイアウトファイルをテキストタブで開いてください。
  2. ConstraintLayoutタグの上にカーソルを当てて、Alt+Enter(Macの場合Option+Enter)を押してください。インテンションメニューを(”quick fix”メニュー)が開きます。
  3. Convert to data binding layoutを選択してください。これによりレイアウトが<layout>によりラップされ、その中に<data>タグが追加されます。
  4. 必要であればトップまでスクロールして戻り、<data>タグの中で、sleepという変数を宣言してください。
  5. typeをSleepNightの完全修飾名である、com.example.android.trackmysleepquality.database.SleepNightとしてください。
    変更後の<data>タグは以下のようになります。
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Bindingオブジェクトの生成を強制するために、Build > Clean Projectを選択肢、その後Build > Rebuild Projectを選択してください。(もし問題が発生している場合は、File > Invalidate Caches / Restartを選択してください)
    関連するコードと一緒にListItemSleepNightBindingバインディングオブジェクトがプロジェクトのgeneratedファイルに追加されます。

ステップ2:データバインディングを使ってアイテムレイアウトをインフレートする

  1. SleepNightAdapter.ktを開いてください。
  2. ViewHolderクラス内のonCreateViewHolder()メソッドを見つけてください。
  3. view変数の宣言文を削除してください。

削除するコード:

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. view変数があった場所に、新しくbindingという名前の変数を宣言し、ListItemSleepNightBindingバインディングオブジェクトをインフレートします。以下のようにコードを追加してください。必要なbindingオブジェクトのインポートを行ってください。
val binding =ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. 関数の最後、viewを返す代わりにbindingを返してください。
return ViewHolder(binding)
  1. エラーを取り除くために、カーソルをbindingという文字の上に置き、Alt+Enter(Macの場合Option+Enter)を押してインテンションメニューを開いてください。
  2. Change parameter ‘itemView’ type of primary constructor of class ‘ViewHolder’ to ‘ListItemSleepNightBinding’を選択してください。これによりViewHolderクラスのパラメーター型が更新されます。
d7213f958ae695b5.png
  1. シグネチャの変化を確認するために、ViewHolderのクラス宣言までスクロールして戻ってください。from()メソッド中のitemViewをbindingに変更したので、itemViewに対するエラーが表示されています。

ViewHolderクラス宣言内のitemViewの上で右クリックし、Refactor > Renameを選択してください。名前をbindingに変更してください。

  1. コンストラクタのパラメーター、bindingにvalを接頭語を付けて、プロパティにしてください。
  2. 親クラスRecyclerView.ViewHolderの呼び出し内のbindingパラメーターをbinding.rootに変更してください。
    Viewを渡す必要があり、binding.rootはアイテムレイアウトのルートであるConstraintLayoutです。
  3. 最終的なクラス宣言は以下のようになります。
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

まだfindViewById()の呼び出しに対するエラーが表示されていると思います。
次のステップでこれを解消していきます。

ステップ3:findViewById()を置き換える

ここまででsleepLength、quality、qualityImageプロパティのfindViewById()の呼び出しを bindingオブジェクトを使ったやり方に変更できる準備が整いました。

  1. sleepLength、quality、qualityImageの初期化文をbindingオブジェクトを使うように変更します。以下のように変更してください。この変更後、一切のエラーが消えます。
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

bindingオブジェクトがあれば、今後sleepLength、quality、qualityImageプロパティを定義する必要はありません。DataBindingがキャッシュしてくれるので、これらのプロパティを宣言する必要がなくなるのです。

  1. sleepLength、quality、qualityImageプロパティの上で右クリックし、Refactor > Inlineを選択、またはControl+Command+N(Macの場合Option+Command+N)を押してください。Inline all references and remove the propertyにチェックを入れて、Refactorをクリックしてください。

  2. アプリを起動してください。(エラーが表示されている場合は、Clean、Recuildする必要があります)