MutableLiveData
はLiveData
で保護されているのに対し、setValue()
およびpostValue()
メソッドをパブリックにすることでのみLiveData
と異なるようです。
LiveData
自体で単純にこれらのメソッドをpublicとして定義するのではなく、この変更に対して別のクラスを作成する理由は何ですか?
一般的に言って、このような形式の継承(特定のメソッドの可視性を高めることが唯一の変更)はよく知られた慣行であり、それが役立つ可能性のあるシナリオは何ですか(すべてのコードにアクセスできると仮定して)?
LiveData-Android Developer Documentation では、LiveData
の場合、setValue()
およびpostValue()
メソッドがパブリックではないことがわかります。
一方、 MutableLiveData-Android Developer Documentation では、MutableLiveData
が内部的にLiveData
を拡張し、LiveData
の2つのマジックメソッドがpubliclyであることがわかります。 これで利用可能であり、setValue()
&postValue()
です。
setValue()
:値を設定し、すべてのアクティブなオブザーバに値をディスパッチします。メインスレッドから呼び出す必要があります。
postValue()
:メインスレッドにタスクをポストして、setValue()
によって設定された値をオーバーライドします。バックグラウンドスレッドから呼び出す必要があります。
したがって、LiveData
はimmutableです。 MutableLiveData
はLiveData
で、mutable&thread-safeです。
これは、MutableLiveData.Java
ファイル全体です。
package androidx.lifecycle;
/**
* {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
*
* @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
そのため、違いはpostValue
とsetValue
をパブリックにすることによってのみ生じます。
私が頭から思い出すことができるユースケースの1つは、Kotlinで Backing Property を使用したカプセル化です。 LiveData
クラスでの操作にMutableLiveData
を使用できる場合でも、ViewModel
をフラグメント/アクティビティ(UIコントローラー)に公開できます。
class TempViewModel : ViewModel() {
...
private val _count = MutableLiveData<Int>()
val count: LiveData<Int>
get() = _count
public fun incrementCount() = _score.value?.plus(1)
...
}
これにより、UIコントローラーは、値を編集することなく、値を監視することしかできなくなります。明らかに、UIコントローラーはincrementCount()
のようなTempViewModel
のパブリックメソッドを使用して値を編集できます。
注:可変/不変の混乱を明確にするために-
data class User(var name: String, var age: Int)
class DemoLiveData: LiveData<User>()
var demoLiveData: LiveData<User>? = DemoLiveData()
fun main() {
demoLiveData?.value = User("Name", 23) // ERROR
demoLiveData?.value?.name = "Name" // NO ERROR
demoLiveData?.value?.age = 23 // NO ERROR
}