Why there's a separate MutableLiveData subclass of LiveData?

两盒软妹~` 提交于 2019-11-27 00:32:50

问题


It looks like MutableLiveData differs from LiveData only by making the setValue() and postValue() methods public, whereas in LiveData they are protected.

What are some reasons to make a separate class for this change and not simply define those methods as public in the LiveData itself?

Generally speaking, is such a form of inheritance (increasing the visibility of certain methods being the only change) a well-known practice and what are some scenarios where it may be useful (assuming we have access to all the code)?


回答1:


In LiveData - Android Developer Documentation, you can see that for LiveData, setValue() & postValue() methods are not public.

Whereas, in MutableLiveData - Android Developer Documentation, you can see that, MutableLiveData extends LiveData internally and also the two magic methods of LiveData is publicly available in this and they are setValue() & postValue().

setValue() : set the value and dispatch the value to all the active observers, must be called from main thread.

postValue() : post a task to main thread to override value set by setValue(), must be called from background thread.

So, LiveData is immutable. MutableLiveData is LiveData which is mutable & thread-safe.




回答2:


This is the whole MutableLiveData.java file:

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);
    }
}

So yes, the difference comes only by making postValue and setValue public.

One use case that I can recall off of my head is for encapsulation using Backing Property in Kotlin. You can expose LiveData to your Fragment/Activity (UI Controller) even though you can have MutableLiveData for manipulation in your ViewModel class.

    class TempViewModel : ViewModel() {
        ...
        private val _count = MutableLiveData<Int>()
        val count: LiveData<Int>
            get() = _count
        public fun incrementCount() = _score.value?.plus(1)
        ...
    }

This way your UI Controller will only be able to observe values without being able to edit them. Obviously, your UI Controller can edit values using public methods of TempViewModel like incrementCount().

Note: To clarify mutable/immutable confusion -

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
}


来源:https://stackoverflow.com/questions/46814158/why-theres-a-separate-mutablelivedata-subclass-of-livedata

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!