106

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)?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Alexander Kulyakhtin
  • 47,782
  • 38
  • 107
  • 158
  • 12
    it is a design decision. `LiveData` is immutable, since the client can't change the internal state, therefore thread-safe – Blackbelt Oct 18 '17 at 15:48

4 Answers4

151

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.

Daniel
  • 2,415
  • 3
  • 24
  • 34
Sneh Pandya
  • 8,197
  • 7
  • 35
  • 50
  • 50
    It's not really that LiveData is immutable, just that it can't be modified _outside_ of the ViewModel class. The ViewModel class can modify it however it wants (e.g. a timer ViewModel). You would use MutableLiveData if you wanted to modify it outside of the ViewModel class. – Elliptica Sep 19 '18 at 21:32
  • in which scenarios i need to use custom livedata class? – Pavel Poley Oct 03 '18 at 08:38
  • 2
    Let's take this scenario, an app with the repository pattern(Server + Room) where Room is the Single Source of truth. App get data only from Room, while Room get it's update from the server. Is mutableLiveData the must use because the data from the server update Room, or LiveData can be use? – Dr4ke the b4dass Nov 13 '18 at 20:25
  • 7
    LiveData is abstract, so you cannot create directly a LiveData object without extending it. MutableLiveData extends LiveData. – Serdar Samancıoğlu Dec 27 '18 at 08:32
  • **postValue** may be called from any thread. **setValue** has to be called by the main thread. – Kurt Huwig Dec 03 '19 at 11:16
  • 1
    Links to LiveData and MutableLiveData direct to deprecated documentation. Why when I suggested an edit with actual links it was rejected? – Daniel Dec 03 '19 at 13:38
  • 1
    @Daniel not sure why it was rejected by other reviewers in the review queue. I've approved the change, thanks! :) – Sneh Pandya Dec 10 '19 at 06:24
  • When do we want to use mutable LiveData vs regular LiveData? – IgorGanapolsky Feb 10 '20 at 19:03
  • 1
    @IgorGanapolsk The Repo (and maybe ViewModel) should use a mutable LiveData to represent data that mutates. The Views should always just use LiveData. – Mooing Duck Apr 13 '20 at 00:37
15

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
}
GuilhermeMagro
  • 321
  • 1
  • 10
Ananth
  • 2,597
  • 1
  • 29
  • 39
5

MutableLiveData is extending from LiveData. LiveData's protected methods can only be addressed by self or subclasses. So in this case MutableLiveData being a sub class of LiveData can access these protected methods.

What you would like to do, is observe on an instance and see if there are any changes. But at the same time you do not want any "outsiders" to change that instance you are observing. In a sense this creates a problem, as you would like to have an object that is and changeable, to update any new status, and not changeable, to make sure nobody who shouldn't can update this instance. These two features conflict with each other but can be solved by creating an extra layer.

So what you do is extend your class, LiveData, with a class that can access its methods. The sub layer, in this case MutableLiveData, is able to access the protected methods of its parent (/super).

Now you start creating instances, and create your observer instance of MutableLiveData. At the same time you create a LiveData instance referring to this same instance. Because MutableLiveData extends LiveData, any MutableLiveData instance is a LiveData object and can therefore be referenced by a LiveData variable.

Now the trick is almost done. You expose only the LiveData instance, nobody can use its protected methods, nor can cast it to it's super (maybe at compile time, but it wouldnt run: RunTime error). And you keep the actual sub class instance private, so it can only be changed by those who own the instance, using the instance's methods.

//create instance of the sub class and keep this private
private val _name: MutableLiveData<String> = MutableLiveData<String>()
//create an instance of the super class referring to the same instance
val name: LiveData<String> = _name
//assign observer to the super class, being unable to change it
name.value.observe(.....)

Now the super class notifies when any changes are applied.

//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)

Blockquote 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)?

Yes, it is quite well-known and this described above is a common scenario. Remove the observer pattern, and just make it in a set/get form would just as much benefit from it. Depending ofc where you implement it, no golden rules in the end.

Khamaseen
  • 326
  • 3
  • 9
-3

LiveData and MutableLiveData are two classes in Android Jetpack that are used to manage data in a lifecycle-aware way. They are both observable, which means that they can be listened to for changes in their data. However, there are some key differences between the two classes:

LiveData is immutable. This means that the value of a LiveData object cannot be changed directly. Instead, you must create a new LiveData object with the new value. This helps to prevent data corruption and makes it easier to reason about the state of your application. MutableLiveData is mutable. This means that the value of a MutableLiveData object can be changed directly. This can be useful for cases where you need to update the data in response to user input or other events. However, it is important to use MutableLiveData carefully, as it can lead to data corruption if not used correctly. In general, you should use LiveData when you want to create an immutable data source. This is the most common use case for LiveData. You should use MutableLiveData when you need to be able to change the data directly. This is less common, but it can be useful in some cases. Automatic lifecycle management Yes Yes Use cases Creating an immutable data source Updating data directly I hope this helps! Let me know if you have any other q

  • 2
    AI-generated answers are not welcomed on this site. See https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned – Eric Aya Aug 16 '23 at 11:59