この Codelab は、Android Kotlin の基礎コースの一部です。このコースを最大限に活用するには、Codelab を順番に進めることをおすすめします。コースのすべての Codelab は、Android Kotlin の基礎の Codelab のランディング ページに一覧表示されています。
はじめに
前の Codelab では、TrackMySleepQuality アプリを更新して、睡眠の質に関するデータを RecyclerView
に表示しました。最初の RecyclerView
を作成したときに学んだ手法は、それほど大きくないシンプルなリストを表示するほとんどの RecyclerViews
に十分です。ただし、大規模なリストでの RecyclerView
の効率を高め、複雑なリストやグリッドでのコードの保守と拡張を容易にする手法は数多くあります。
この Codelab では、前の Codelab で作成した睡眠トラッカー アプリをベースにアプリを作成します。睡眠データのリストを更新するより効果的な方法と、RecyclerView
でデータ バインディングを使用する方法を学びます。(前の Codelab のアプリがない場合は、この Codelab のスターター コードをダウンロードできます)。
前提となる知識
- アクティビティ、フラグメント、ビューを使用して基本的なユーザー インターフェースを構築する。
- フラグメント間の移動、
safeArgs
を使用してフラグメント間でデータを渡す。 - モデル、モデル ファクトリ、変換、
LiveData
、オブザーバーを表示します。 Room
データベースを作成し、DAO を作成して、エンティティを定義する方法。- データベースやその他の長時間実行タスクにコルーチンを使用する方法。
Adapter
、ViewHolder
、アイテム レイアウトを使用して基本的なRecyclerView
を実装する方法。
学習内容
DiffUtil
を使用してRecyclerView
で表示されるリストを効率的に更新する方法。RecyclerView
でデータ バインディングを使用する方法。- バインディング アダプタを使用してデータを変換する方法。
演習内容
- このシリーズの前の Codelab で作成した TrackMySleepQuality アプリをベースに構築します。
SleepNightAdapter
を更新して、DiffUtil
を使用してリストを効率的に更新します。- バインディング アダプターを使用してデータを変換し、
RecyclerView
のデータ バインディングを実装します。
睡眠トラッカー アプリには、下の図に示すように、フラグメントで表される 2 つの画面があります。
左側に表示されている最初の画面には、トラッキングの開始と停止のボタンがあります。画面には、ユーザーの睡眠データの一部が表示されます。[消去] ボタンをクリックすると、アプリがユーザーのために収集したすべてのデータが完全に削除されます。右側の 2 つ目の画面は、睡眠の質の評価を選択するための画面です。
このアプリは、UI コントローラ ViewModel
と LiveData
、および Room
データベースを使用して睡眠データを永続化するように設計されています。
睡眠データは RecyclerView
に表示されます。この Codelab では、RecyclerView
の DiffUtil
とデータバインディング部分を構築します。この Codelab を終了すると、アプリの外観はまったく同じになりますが、効率が向上し、スケーリングとメンテナンスが容易になります。
前の Codelab の SleepTracker アプリを引き続き使用することも、GitHub から RecyclerViewDiffUtilDataBinding-Starter アプリをダウンロードすることもできます。
- 必要に応じて、GitHub から RecyclerViewDiffUtilDataBinding-Starter アプリをダウンロードし、Android Studio でプロジェクトを開きます。
- アプリを実行します。
SleepNightAdapter.kt
ファイルを開きます。- コードを調べて、アプリの構造を理解します。下の図は、アダプター パターンで
RecyclerView
を使用して睡眠データをユーザーに表示する方法をまとめたものです。
- アプリは、ユーザー入力から
SleepNight
オブジェクトのリストを作成します。各SleepNight
オブジェクトは、1 泊の睡眠、その時間、質を表します。 SleepNightAdapter
は、SleepNight
オブジェクトのリストをRecyclerView
が使用して表示できるものに適合させます。SleepNightAdapter
アダプターは、リサイクラー ビューがデータを表示するためのビュー、データ、メタ情報を含むViewHolders
を生成します。RecyclerView
はSleepNightAdapter
を使用して、表示するアイテムの数(getItemCount()
)を決定します。RecyclerView
はonCreateViewHolder()
とonBindViewHolder()
を使用して、表示するデータにバインドされたビューホルダーを取得します。
notifyDataSetChanged() メソッドは非効率的です
リスト内のアイテムが変更され、更新が必要であることを RecyclerView
に伝えるために、現在のコードは、次の例に示すように、SleepNightAdapter
の notifyDataSetChanged()
を呼び出します。
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
ただし、notifyDataSetChanged()
はリスト全体が無効になる可能性があることを RecyclerView
に伝えます。その結果、RecyclerView
は画面に表示されていないアイテムも含め、リスト内のすべてのアイテムを再バインドして再描画します。これは不要な作業です。リストが大きい場合や複雑な場合、この処理に時間がかかり、ユーザーがリストをスクロールする際に画面がちらついたり、途切れたりすることがあります。
この問題を解決するには、RecyclerView
に変更内容を正確に伝えます。RecyclerView
は、画面上で変更されたビューのみを更新できます。
RecyclerView
には、単一の要素を更新するための豊富な API があります。notifyItemChanged()
を使用して、アイテムが変更されたことを RecyclerView
に通知できます。同様の関数を、追加、削除、移動されたアイテムに使用できます。すべて手動で行うこともできますが、このタスクは簡単ではなく、かなりの量のコードが必要になる可能性があります。
幸いなことに、もっと良い方法があります。
DiffUtil は効率的で、面倒な作業を代行してくれる
RecyclerView
には、2 つのリストの差を計算するための DiffUtil
というクラスがあります。DiffUtil
は古いリストと新しいリストを受け取り、違いを特定します。追加、削除、変更されたアイテムを検出します。次に、Eugene W. Myers の差分アルゴリズムを使用して、古いリストから新しいリストを作成するために必要な最小限の変更を特定します。
DiffUtil
が変更内容を把握すると、RecyclerView
はその情報を使用して、変更、追加、削除、移動されたアイテムのみを更新できます。これは、リスト全体をやり直すよりもはるかに効率的です。
このタスクでは、SleepNightAdapter
をアップグレードして DiffUtil
を使用し、データの変更に合わせて RecyclerView
を最適化します。
ステップ 1: SleepNightDiffCallback を実装する
DiffUtil
クラスの機能を使用するには、DiffUtil.ItemCallback
を拡張します。
SleepNightAdapter.kt
を開きます。SleepNightAdapter
の完全なクラス定義の下に、DiffUtil.ItemCallback
を拡張するSleepNightDiffCallback
という新しいトップレベル クラスを作成します。SleepNight
を汎用パラメータとして渡します。
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
SleepNightDiffCallback
クラス名にカーソルを置きます。Alt+Enter
(Mac の場合はOption+Enter
)を押して、[Implement Members] を選択します。- 表示されたダイアログで、Shift キーを押しながら左クリックして
areItemsTheSame()
メソッドとareContentsTheSame()
メソッドを選択し、[OK] をクリックします。
これにより、次の図に示すように、2 つのメソッドのスタブがSleepNightDiffCallback
内に生成されます。DiffUtil
は、これらの 2 つのメソッドを使用して、リストとアイテムがどのように変更されたかを判断します。
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
areItemsTheSame()
内で、TODO
を、渡された 2 つのSleepNight
項目oldItem
とnewItem
が同じかどうかをテストするコードに置き換えます。アイテムのnightId
が同じ場合は、同じアイテムであるため、true
を返します。それ以外の場合は、false
を返します。DiffUtil
は、このテストを使用して、アイテムが追加、削除、移動されたかどうかを検出します。
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
}
areContentsTheSame()
内で、oldItem
とnewItem
に同じデータが含まれているかどうか、つまり等しいかどうかを確認します。SleepNight
はデータクラスであるため、この等価性チェックではすべてのフィールドがチェックされます。Data
クラスは、equals
とその他のいくつかのメソッドを自動的に定義します。oldItem
とnewItem
の間に違いがある場合、このコードはDiffUtil
にアイテムが更新されたことを伝えます。
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem
}
RecyclerView
を使用して変更されるリストを表示するのは一般的なパターンです。RecyclerView
は、リストを基盤とする RecyclerView
アダプタの構築に役立つアダプタ クラス ListAdapter
を提供します。
ListAdapter
はリストを追跡し、リストが更新されるとアダプターに通知します。
ステップ 1: アダプターを変更して ListAdapter を拡張する
SleepNightAdapter.kt
ファイルで、SleepNightAdapter
のクラス シグネチャをListAdapter
を拡張するように変更します。- プロンプトが表示されたら、
androidx.recyclerview.widget.ListAdapter
をインポートします。 SleepNightAdapter.ViewHolder
の前に、ListAdapter
の最初の引数としてSleepNight
を追加します。- コンストラクタのパラメータとして
SleepNightDiffCallback()
を追加します。ListAdapter
は、これを使用してリスト内の変更点を把握します。完成したSleepNightAdapter
クラスのシグネチャは次のようになります。
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
SleepNightAdapter
クラス内で、セッターを含むdata
フィールドを削除します。ListAdapter
がリストを追跡してくれるため、この変数は不要になりました。ListAdapter
がこのメソッドを実装するため、getItemCount()
のオーバーライドを削除します。onBindViewHolder()
のエラーを解消するには、item
変数を変更します。data
を使用してitem
を取得する代わりに、ListAdapter
が提供するgetItem(position)
メソッドを呼び出します。
val item = getItem(position)
ステップ 2: submitList() を使用してリストを最新の状態に保つ
コードでは、変更されたリストが利用可能になったときに ListAdapter
に通知する必要があります。ListAdapter
は、リストの新しいバージョンが利用可能であることを ListAdapter
に通知する submitList()
というメソッドを提供します。このメソッドが呼び出されると、ListAdapter
は新しいリストと古いリストを比較し、追加、削除、移動、変更された項目を検出します。次に、ListAdapter
が RecyclerView
で表示されるアイテムを更新します。
SleepTrackerFragment.kt
を開きます。onCreateView()
のsleepTrackerViewModel
のオブザーバーで、削除したdata
変数が参照されているエラーを見つけます。adapter.data = it
をadapter.submitList(it)
の呼び出しに置き換えます。更新されたコードは次のとおりです。
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
- アプリを実行します。実行速度が速くなります。リストが小さい場合は、速度の向上を実感できないかもしれません。
このタスクでは、前の Codelab と同じ手法を使用してデータ バインディングを設定し、findViewById()
の呼び出しを削除します。
ステップ 1: レイアウト ファイルにデータ バインディングを追加する
- [テキスト] タブで
list_item_sleep_night.xml
レイアウト ファイルを開きます。 ConstraintLayout
タグにカーソルを置き、Alt+Enter
キー(Mac の場合はOption+Enter
キー)を押します。インテンション メニュー(クイック フィックス メニュー)が開きます。- [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
バインディング オブジェクトと関連するコードが、プロジェクトの生成されたファイルに追加されます。
ステップ 2: データ バインディングを使用してアイテム レイアウトを拡張する
SleepNightAdapter.kt
を開きます。ViewHolder
クラスでfrom()
メソッドを見つけます。view
変数の宣言を削除します。
削除するコード:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
view
変数があった場所に、次に示すように、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
、qualityString
、qualityImage
の初期化を変更して、binding
オブジェクトのビューを使用します。これで、コードにエラーが表示されなくなります。
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
バインディング オブジェクトが配置されているため、sleepLength
、quality
、qualityImage
の各プロパティを定義する必要はなくなりました。DataBinding
はルックアップをキャッシュに保存するため、これらのプロパティを宣言する必要はありません。
sleepLength
、quality
、qualityImage
プロパティ名を右クリックします。[Refactor > Inline] を選択するか、Control+Command+N
(Mac の場合はOption+Command+N
)を押します。- アプリを実行します(エラーがある場合は、プロジェクトのクリーンと再ビルドが必要になることがあります)。
このタスクでは、バインディング アダプターでデータ バインディングを使用し、ビューにデータを設定するようにアプリをアップグレードします。
前の Codelab では、Transformations
クラスを使用して LiveData
を取得し、テキスト ビューに表示する書式設定された文字列を生成しました。ただし、異なる型や複雑な型をバインドする必要がある場合は、データ バインディングでそれらの型を使用できるようにバインディング アダプタを提供できます。バインディング アダプターは、データを取得して、テキストや画像などのビューをバインドするためにデータ バインディングで使用できるものに変換するアダプターです。
3 つのバインディング アダプタ(高品質の画像用と、テキスト フィールドごとに 1 つ)を実装します。要するに、バインディング アダプターを宣言するには、アイテムとビューを受け取るメソッドを定義し、それに @BindingAdapter
アノテーションを付けます。メソッドの本体で、変換を実装します。Kotlin では、データを受け取るビュークラスの拡張関数としてバインディング アダプタを作成できます。
ステップ 1: バインディング アダプタを作成する
この手順では複数のクラスをインポートする必要がありますが、個別に呼び出されることはありません。
SleepNightAdapater.kt
を開きます。ViewHolder
クラス内でbind()
メソッドを見つけ、このメソッドの機能を確認します。binding.sleepLength
、binding.quality
、binding.qualityImage
の値を計算するコードを取得し、アダプタ内で使用します。(今のところ、コードはそのままにしておきます。後のステップで移動します)。sleeptracker
パッケージで、BindingUtils.kt
というファイルを作成して開きます。TextView
でsetSleepDurationFormatted
という拡張関数を宣言し、SleepNight
を渡します。この関数は、睡眠時間を計算してフォーマットするためのアダプターになります。
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
setSleepDurationFormatted
の本文で、ViewHolder.bind()
の場合と同様に、データをビューにバインドします。convertDurationToFormatted()
を呼び出し、TextView
のtext
を書式設定されたテキストに設定します。(これはTextView
の拡張関数であるため、text
プロパティに直接アクセスできます)。
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
- このバインディング アダプターをデータ バインディングに伝えるには、関数に
@BindingAdapter
アノテーションを付けます。 - この関数は
sleepDurationFormatted
属性のアダプターであるため、@BindingAdapter
の引数としてsleepDurationFormatted
を渡します。
@BindingAdapter("sleepDurationFormatted")
- 2 番目のアダプタは、
SleepNight
オブジェクトの値に基づいて睡眠の質を設定します。TextView
にsetSleepQualityString()
という名前の拡張関数を作成し、SleepNight
を渡します。 - 本文で、
ViewHolder.bind()
の場合と同様に、データをビューにバインドします。convertNumericQualityToString
を呼び出してtext
を設定します。 - 関数に
@BindingAdapter("sleepQualityString")
アノテーションを付けます。
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
- 3 つ目のバインディング アダプターは、画像ビューに画像を設定します。以下に示すように、
ImageView
で拡張関数を作成し、setSleepImage
を呼び出し、ViewHolder.bind()
のコードを使用します。
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
setImageResource(when (item.sleepQuality) {
0 -> R.drawable.ic_sleep_0
1 -> R.drawable.ic_sleep_1
2 -> R.drawable.ic_sleep_2
3 -> R.drawable.ic_sleep_3
4 -> R.drawable.ic_sleep_4
5 -> R.drawable.ic_sleep_5
else -> R.drawable.ic_sleep_active
})
}
ステップ 2: SleepNightAdapter を更新する
SleepNightAdapter.kt
を開きます。bind()
メソッド内のすべてを削除します。データ バインディングと新しいアダプターを使用して、この作業を行うことができるためです。
fun bind(item: SleepNight) {
}
bind()
内で、item
にスリープを割り当てます。これは、バインディング オブジェクトに新しいSleepNight
を通知する必要があるためです。
binding.sleep = item
- その行の下に
binding.executePendingBindings()
を追加します。この呼び出しは、保留中のバインディングをすぐに実行するようにデータ バインディングに要求する最適化です。RecyclerView
でバインディング アダプターを使用する場合は、常にexecutePendingBindings()
を呼び出すことをおすすめします。ビューのサイズ設定をわずかに高速化できるためです。
binding.executePendingBindings()
ステップ 3: XML レイアウトにバインディングを追加する
list_item_sleep_night.xml
を開きます。ImageView
で、画像を設定するバインディング アダプターと同じ名前のapp
プロパティを追加します。以下に示すように、sleep
変数を渡します。
このプロパティは、アダプターを介してビューとバインディング オブジェクト間の接続を作成します。sleepImage
が参照されるたびに、アダプターはSleepNight
からデータを適応させます。
app:sleepImage="@{sleep}"
sleep_length
とquality_string
のテキスト ビューについても同様に処理します。sleepDurationFormatted
またはsleepQualityString
が参照されるたびに、アダプターはSleepNight
からデータを適応させます。
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
- アプリを実行します。以前とまったく同じように動作します。バインディング アダプタは、データの変更に応じてビューのフォーマットと更新を行うすべての処理を担当するため、
ViewHolder
が簡素化され、コードの構造が以前よりも大幅に改善されます。
ここ数回のエクササイズで同じリストが表示されています。これは、Adapter
インターフェースを使用すると、さまざまな方法でコードを設計できることを示すための設計です。コードが複雑になるほど、アーキテクチャを適切に設計することが重要になります。本番環境アプリでは、これらのパターンやその他のパターンが RecyclerView
とともに使用されます。どのパターンも機能し、それぞれにメリットがあります。どちらを選択するかは、構築する内容によって異なります。
おめでとうございます。これで、Android での RecyclerView
の習得はほぼ完了です。
Android Studio プロジェクト: RecyclerViewDiffUtilDataBinding。
DiffUtil
:
RecyclerView
には、2 つのリストの差を計算するためのDiffUtil
というクラスがあります。DiffUtil
には、2 つのリストの違いを把握するために拡張するItemCallBack
というクラスがあります。ItemCallback
クラスで、areItemsTheSame()
メソッドとareContentsTheSame()
メソッドをオーバーライドする必要があります。
ListAdapter
:
- リスト管理を無料で利用するには、
RecyclerView.Adapter
の代わりにListAdapter
クラスを使用します。ただし、ListAdapter
を使用する場合は、他のレイアウト用に独自のアダプターを作成する必要があります。この Codelab では、その方法について説明します。 - Android Studio でインテンション メニューを開くには、コードの任意の項目にカーソルを置き、
Alt+Enter
(Mac の場合はOption+Enter
)を押します。このメニューは、コードのリファクタリングやメソッドを実装するためのスタブの作成に特に便利です。メニューはコンテキスト依存型であるため、正しいメニューを表示するには、カーソルを正確に配置する必要があります。
データ バインディング:
- アイテム レイアウトでデータ バインディングを使用して、データをビューにバインドします。
バインディング アダプター:
- 以前は
Transformations
を使用してデータから文字列を作成していました。異なる型や複雑な型のデータをバインドする必要がある場合は、データ バインディングがそれらを使用できるようにバインディング アダプターを提供します。 - バインディング アダプターを宣言するには、アイテムとビューを受け取るメソッドを定義し、そのメソッドに
@BindingAdapter
アノテーションを付けます。Kotlin では、バインディング アダプターをView
の拡張関数として記述できます。アダプターが適応するプロパティの名前を渡します。次に例を示します。
@BindingAdapter("sleepDurationFormatted")
- XML レイアウトで、バインディング アダプタと同じ名前の
app
プロパティを設定します。データを含む変数を渡します。次に例を示します。
.app:sleepDurationFormatted="@{sleep}"
Udacity のコース:
Android デベロッパー ドキュメント:
- RecyclerView でリストを作成する
RecyclerView
DiffUtil
- データ バインディング ライブラリ
- バインディング アダプター
notifyDataSetChanged()
Transformations
その他のリソース:
このセクションでは、インストラクター主導のコースの一環として、この Codelab に取り組んでいる生徒向けに考えられる宿題をいくつか示します。インストラクターは、以下のようなことを行えます。
- 必要に応じて宿題を与える
- 宿題の提出方法を生徒に伝える
- 宿題を採点する
インストラクターは、これらの提案を必要なだけ使用し、必要に応じて他の宿題も自由に与えることができます。
この Codelab に独力で取り組む場合は、これらの宿題を自由に使用して知識をテストしてください。
以下の質問に回答してください
問題 1
DiffUtil
を使用するのに必要なのは、次のどれですか。該当するものをすべて選択してください。
▢ ItemCallBack
クラスを拡張します。
▢ areItemsTheSame()
をオーバーライドします。
▢ areContentsTheSame()
をオーバーライドします。
▢ データ バインディングを使用してアイテム間の違いをトラッキングする。
質問 2
バインディング アダプターの説明として正しいものは次のうちどれですか。
▢ バインディング アダプターは @BindingAdapter
アノテーションが付いた関数です。
▢ バインディング アダプタを使用すると、データ形式とビューホルダーを分離できます。
▢ バインディング アダプターを使用するには RecyclerViewAdapter
を使用する必要があります。
▢ バインディング アダプターは、複雑なデータを変換する必要がある場合に適したソリューションである。
質問 3
バインディング アダプターの代わりに Transformations
を使用することを検討すべきなのは、どのような場合ですか?該当するものをすべて選択してください。
▢ データがシンプルである。
▢ 文字列をフォーマットしている。
▢ リストが長すぎる。
▢ ViewHolder
に含まれるビューが 1 つのみである。
次のレッスンに進む: