
みなさまこんにちは〜!
メモリアインクのすだです。
LiveDataには便利な機能が様々ありますが、
今回はmap・switchMap・MediatorLiveDataの3つについて
実際のコードを使って解説していきます。
この記事を読んでわかること…
・LiveDataにおけるmap()の使い方
・LiveDataにおけるswitchMap()の使い方
・LiveDataにおけるMediatorLiveDataの使い方
LiveDataやViewModelに関しては、以下の記事で詳しく解説しています。
ぜひ合わせてご覧ください。


環境
- Kotlin (ver 1.9.0)
- Android Studio (Giraffe | 2022.3.1 Patch 3)
Transformationsとは?LiveDataにおけるmap・switchMapの使い方
Transformationsは、LiveDataを変換(transform)するための便利な関数がまとまったクラスです。
主に以下の2つの関数を提供しています:
LiveDataにおけるTransformations.map()の使い方
map()は、あるLiveDataの値を変換して、新しいLiveDataとして使いたいとき に便利です。
例えば、「名前を大文字に変換して表示したい」場合に、以下のように実装することができます。
ViewModel
class UserViewModel : ViewModel() {
val userName = MutableLiveData("taro")
val displayName: LiveData<String> = Transformations.map(userName) {
it.uppercase() // ← 大文字に変換
}
fun fetchUserName() {
// ここでは仮に取得した名前として"hanako"をセット
userName.value = "hanako"
}
}
→このように Transformations.map()
を使うと、
元の LiveData の値を別の LiveData に変換して扱うことができます。userName.value = "hanako"
と代入すると、displayName には “HANAKO” という変換済みの値が反映されます。
UI側
viewModel.displayName.observe(this) { name ->
textView.text = "ユーザー名:$name"
}
// データを取得(=名前をセット)
viewModel.fetchUserName()
LiveDataにおけるTransformations.switchMap()の使い方
switchMapは、あるLiveDataの値によって別のLiveDataを動的に切り替えたいとき に使います。
例えば、「ユーザーIDを変更するたびに、そのIDに対応するユーザー情報を取得・表示したい場合」に以下のように実装できます。
ViewModel
class UserViewModel(private val userRepository: UserRepository) : ViewModel() {
val selectedUserId = MutableLiveData<String>()
val userInfo: LiveData<User> = Transformations.switchMap(selectedUserId) { userId ->
userRepository.getUserLiveData(userId) // LiveData<User> を返す
}
fun selectUser(userId: String) {
selectedUserId.value = userId
}
}
selectedUserId
の値が変わるたびに、それに応じた LiveData<User>
を生成し直すことで、Transformations.switchMap()
によって 監視対象のLiveDataそのものが切り替わる仕組みになっています。
UI側
viewModel.userInfo.observe(this) { user ->
textView.text = "${user.name} さん(${user.age}歳)"
}
// ボタンを押したときなどにIDを切り替える想定
viewModel.selectUser("123")
MediatorLiveDataの使い方
MediatorLiveDataは、2つ以上のLiveDataの変更をまとめて1つのLiveDataとして扱いたいとき に便利です。
ViewModel
class ProfileViewModel : ViewModel() {
// 名前と年齢のLiveData
val name = MutableLiveData("佐藤")
val age = MutableLiveData(30)
// MediatorLiveDataで名前+年齢を合成したプロフィール文を生成
val profile: MediatorLiveData<String> = MediatorLiveData<String>().apply {
// 名前が変わったとき
addSource(name) { newName ->
val currentAge = age.value ?: "?"
value = "$newName さん(${currentAge}歳)"
}
// 年齢が変わったとき
addSource(age) { newAge ->
val currentName = name.value ?: "?"
value = "$currentName さん(${newAge}歳)"
}
}
// 名前を変更するメソッド
fun updateName(newName: String) {
name.value = newName
}
// 年齢を変更するメソッド
fun updateAge(newAge: Int) {
age.value = newAge
}
}
MediatorLiveData().apply
を使用すると、addSource()
というメソッドが「変化があったときに再計算するトリガー」を登録してくれます。
UI側
viewModel.profile.observe(this) { profileText ->
textView.text = profileText
}
// ボタンクリックなどで値を変更
viewModel.updateName("田中")
viewModel.updateAge(28)
状態の組み合わせや依存が複雑になるほど、これらの機能を使うとUIコードがよりスッキリします。
まとめ
いかがでしたでしょうか!
LiveDataの変換系テクニックを覚えると、
ViewModelの中で状態をしっかり設計でき、UIコードがスッキリします。
ぜひ実装に取り入れてみてください!



技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
自分の市場価値をさらに向上させてみませんか?
それではまた次の記事でお会いしましょう!
コメント