Fry in the Web

次からこうしようと思ったことを書き残しておきます

MediatorLiveDataとTransformation

Mediator LiveDataとは

各種LiveDataとViewの仲介役をつとめてくれるライブデータです。

例えば、ゲームを作っていてアイテムA、アイテムBのいずれかの所持数が10を切ると危険の表示が出るような状況を考えてみましょう。 このような状況で解決策の一つとしてItemAの所持数が変化したことを伝えるLivedataを作り、同様のものをItemBについても作成すると考えてみましょう。 各データをView(ActivityやFragmant)で監視することによって、表示を切り替えることが可能です。

Solution 1

val itemACount:MutableLiveData<Int>=MutableLiveData()
val itemBCount:MutableLiveData<Int>=MutableLiveData()

使用側では

itemACount.observe{this,Obsrver{Toast.makeText(this,"Item Is Not Full",Toast.LONG_LENGTH).show()}} //簡単のためToastにしています。
itemBCount.observe{this,Obsrver{Toast.makeText(this,"Item Is Not Full",Toast.LONG_LENGTH).show()}}

可能ではありますが、すべてのデータに対してObserveを呼ぶのは少し面倒です。

そこで今回の紹介するMediatorLiveDataを使用することにより、複数のLiveDataがあたかも一つであるかのように扱うことができます。

Solution 2

val itemACount:MutableLiveData<Int>=MutableLiveData()
val itemBCount:MutableLiveData<Int>=MutableLiveData()

val mediator=MediatorLiveData<Int>().apply{
        addSource(itemACount) {this.value=it}
        addSource(itemBCount) {this.value=it}
}  
val itemIsNotFull: LiveData<Boolean> =Transformations.map(mediator) {
        if (it=<10)
           return@map true
        else
            false
    }

MediatorLiveDataは単にまとめる役割のみをもっています、そこでMediator自身にAddSource内で値をセットします。

使う側では通常通りに

itemIsNotFull.observe{this,Obsrver{Toast.makeText(this,"Is Not Full",Toast.LONG_LENGTH).show()}}

と行えば、ItemA ItemBのどれかが10以下になったときにLiveDataに通知してくれます。

一行でまとめられるので楽です。

雑(な)感(想)

公式の方法に沿ってTransformations を使用したんだけど、Mediator LiveData 内部で変換しちゃだめなのかな? 多分拡張性の観点から(例えば10以下じゃなくて5以下とかを追加したくなったときに困るから)そうしてるんだろうね