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)?
By using LiveData we can only observe the data and cannot set the data. MutableLiveData is mutable and is a subclass of LiveData. In MutableLiveData we can observe and set the values using postValue() and setValue() methods (the former being thread-safe) so that we can dispatch values to any live or active observers.
So, LiveData is immutable. MutableLiveData is LiveData which is mutable & thread-safe.
While using the Main thread to change the data, you should use the setValue method of the MutableLiveData class and while using the background thread to change the LiveData, you should use the postValue method of the MutableLiveData class.
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.
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() = _count.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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With