【Android】map や switchMap で LiveData を変換する
今回は、map や switchMap で LiveData を変換する方法を解説します。
なお、ここに掲載しているソースコードは以下の環境で動作確認しています。
- Android Studio Bumblebee | 2021.1.1 Patch 2
- JDK 11.0.11
- Android Gradle Plugin 7.1.2
- Kotlin 1.6.10
- Gradle 7.4.1
- androidx.lifecycle 2.4.1
また、実際に LiveData の map や switchMap を使用する際は、以下のようにアプリの build.gradle ファイルに lifecycle-livedata-ktx
をインポートしてください。
dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.1"
}
map とは?
map は LiveData の拡張関数の 1 つです。
public inline fun <X, Y> LiveData<X>.map( crossinline transform: (X) -> Y ): LiveData<Y>
この関数の使い方は、変換したい LiveData に対して変換処理 transform を渡すだけです。そうすると、変換元の LiveData が変更されたとき、map に渡した transform が実行されて、変換後の LiveData を取得できます。
例えば、整数値を持つ LiveData の値を 2 倍にしたい場合、以下のような使い方をします。
val before = MutableLiveData(0) // before を 2 倍にして返す。 val after = before.map { it * 2 }
内部的には MediatorLiveData で実装されており、監視対象が 1 つだけの MediatorLiveData のような振る舞いをします。
switchMap とは?
switchMap も map と同様に LiveData の拡張関数の 1 つです。
public inline fun <X, Y> LiveData<X>.switchMap( crossinline transform: (X) -> LiveData<Y> ): LiveData<Y>
使い方も、map と同様に変換したい LiveData に対して変換処理 transform を渡すだけです。
map との違いは、変換処理 transform の中で変換結果を返すとき、値の型ではなくて LiveData 型で返す必要があることです。
よって、さきほどの整数値を 2 倍にする例を switchMap で実装する場合、以下のようになります。
val before = MutableLiveData(0) // before を 2 倍にして返す。 val after = before.switchMap { MutableLiveData(it * 2) }
switchMap の使い道は、戻り値が LiveData 型のメソッドで変換を行いたいときでしょう。
例えば、Room データベースの DAO で、ID を引数に渡すとその ID に紐付くユーザーデータを読み出すメソッドを変換に使いたい場合です。
@Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") fun loadUserById(id: Int): LiveData<User> }
class MainViewModel( private val id: Int, private val dao: UserDao ) : ViewModel() { private val _id = MutableLiveData(id) // ID からユーザーデータを読み出す。 val user = _id.switchMap { dao.loadUserById(it) } fun setId(id: Int) { _id.value = id } ︙ }
上記のように switchMap であれば、そのメソッドの戻り値をそのまま返すだけで、LiveData 型のユーザーデータを取得できます。
また、上記の user
は LiveData 型なので、user
を LiveData#observe にて監視しておけば、ID が変わるたびに user
の変更を補足できるようになります。