Android Kotlin基礎講座 07.2:DiffUtilとRecycleViewのデータバインディング
目次
タスク:RecyclerViewにDataBindingを使う
このタスクでは、前回の記事で使われた技術と同じ技術を用いてデータバインディングをセットアップします。またfindViewById()の呼び出しを排除していきます。
ステップ1:レイアウトファイルにデータバインディングを追加する
- list_item_sleep_night.xmlレイアウトファイルをテキストタブで開いてください。
- ConstraintLayoutタグの上にカーソルを当てて、Alt+Enter(Macの場合Option+Enter)を押してください。インテンションメニューを(”quick fix”メニュー)が開きます。
- Convert to data binding layoutを選択してください。これによりレイアウトが<layout>によりラップされ、その中に<data>タグが追加されます。
- 必要であればトップまでスクロールして戻り、<data>タグの中で、sleepという変数を宣言してください。
- typeをSleepNightの完全修飾名である、com.example.android.trackmysleepquality.database.SleepNightとしてください。
変更後の<data>タグは以下のようになります。
<data>
<variable
name="sleep"
type="com.example.android.trackmysleepquality.database.SleepNight"/>
</data>
- Bindingオブジェクトの生成を強制するために、Build > Clean Projectを選択肢、その後Build > Rebuild Projectを選択してください。(もし問題が発生している場合は、File > Invalidate Caches / Restartを選択してください)
関連するコードと一緒にListItemSleepNightBindingバインディングオブジェクトがプロジェクトのgeneratedファイルに追加されます。
ステップ2:データバインディングを使ってアイテムレイアウトをインフレートする
- SleepNightAdapter.ktを開いてください。
- ViewHolderクラス内のonCreateViewHolder()メソッドを見つけてください。
- view変数の宣言文を削除してください。
削除するコード:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
- view変数があった場所に、新しくbindingという名前の変数を宣言し、ListItemSleepNightBindingバインディングオブジェクトをインフレートします。以下のようにコードを追加してください。必要なbindingオブジェクトのインポートを行ってください。
val binding =ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
- 関数の最後、viewを返す代わりにbindingを返してください。
return ViewHolder(binding)
- エラーを取り除くために、カーソルをbindingという文字の上に置き、Alt+Enter(Macの場合Option+Enter)を押してインテンションメニューを開いてください。
- Change parameter ‘itemView’ type of primary constructor of class ‘ViewHolder’ to ‘ListItemSleepNightBinding’を選択してください。これによりViewHolderクラスのパラメーター型が更新されます。
- シグネチャの変化を確認するために、ViewHolderのクラス宣言までスクロールして戻ってください。from()メソッド中のitemViewをbindingに変更したので、itemViewに対するエラーが表示されています。
ViewHolderクラス宣言内のitemViewの上で右クリックし、Refactor > Renameを選択してください。名前をbindingに変更してください。
- コンストラクタのパラメーター、bindingにvalを接頭語を付けて、プロパティにしてください。
- 親クラスRecyclerView.ViewHolderの呼び出し内のbindingパラメーターをbinding.rootに変更してください。
Viewを渡す必要があり、binding.rootはアイテムレイアウトのルートであるConstraintLayoutです。 - 最終的なクラス宣言は以下のようになります。
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
まだfindViewById()の呼び出しに対するエラーが表示されていると思います。
次のステップでこれを解消していきます。
ステップ3:findViewById()を置き換える
ここまででsleepLength、quality、qualityImageプロパティのfindViewById()の呼び出しを bindingオブジェクトを使ったやり方に変更できる準備が整いました。
- sleepLength、quality、qualityImageの初期化文をbindingオブジェクトを使うように変更します。以下のように変更してください。この変更後、一切のエラーが消えます。
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
bindingオブジェクトがあれば、今後sleepLength、quality、qualityImageプロパティを定義する必要はありません。DataBindingがキャッシュしてくれるので、これらのプロパティを宣言する必要がなくなるのです。
- sleepLength、quality、qualityImageプロパティの上で右クリックし、Refactor > Inlineを選択、またはControl+Command+N(Macの場合Option+Command+N)を押してください。Inline all references and remove the propertyにチェックを入れて、Refactorをクリックしてください。
- アプリを起動してください。(エラーが表示されている場合は、Clean、Recuildする必要があります)