【正社員】還元率83%【フリーランス】マージン一律5万円で案件をご紹介させていただきます。 詳細はこちら

【Android】<Kotlin>LiveDataを自在に変換!map・switchMap・MediatorLiveDataの使い方まとめ

【Android】<Kotlin>LiveDataを自在に変換!map・switchMap・MediatorLiveDataの使い方まとめ
すだ

みなさまこんにちは〜!
メモリアインクのすだです。

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つの関数を提供しています:

・Transformations.map()
・Transformations.switchMap()

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エンジニアを目指すなら【ユニゾンキャリア】
を通じて、
自分の市場価値をさらに向上させてみませんか?

それではまた次の記事でお会いしましょう!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

弊社テックブログをご愛読いただきありがとうございます。
当テックブログを運用している株式会社メモリアインクは、
【正社員】還元率83%
【フリーランス】マージン一律5万円で案件のご紹介
と、エンジニアの皆様に分かりやすい形で稼げる仕組みを構築し提供させていただいております。

コメント

コメントする

目次