I have a variable:
private var a = MutableLiveData<MutableList<Int>>()
Variable that I want to assign a value to when the button is clicked.
For example for every click, add a new random int to the list, like: [] -> [5] -> [5,7] -> [5,7,3] -> // etc
How can I add an item to a MutableList of Int that is wrapped in LiveData and empty as default?
I know that in order to add a value in MutableList i should use a.value.add()
but this case i have to first use a.setValue()
cause variabe a is MutableLiveData.
I can't get it, how i should combine this methods. Or is there another better solution?
I searched a lot, but not found the answer.
A
LiveDatastores a single value, and pushes updates to observers. When somethingobserves it, thatObserverwill be called if theLiveDatacurrently has a value. Then, whenever that value changes, every registered observer will be called again with the new value.To actually change that stored value, you need a
MutableLiveData- this has thesetValue(and similar) functions that allow you to update it. A plainLiveData(whichMutableLiveDatais a subclass of) doesn't allow you to change the value.Generally you're recommended to do this kind of thing, e.g. in your
ViewModel:So internally you hold this
_myLiveDatawhich is mutable, and private to theViewModel. That allows you to callsetValueon it, etc. But you also expose it publicly asmyLiveDatawhich is a non-mutableLiveDatatype. This means that any external consumers can't callsetValueon it, because aLiveDatadoesn't have those.You're basically not telling consumers that it's actually a
MutableLiveData, just that it's aLiveDatain general. That keeps things cleaner, because they can't mess with it without making an effort to do so (e.g. casting it toMutableLiveData). This way, only the owner of the data can set the value on it - everything else only reacts to changes. Anything that needs to update that value needs to go through theViewModel, e.g. through a function. This lets theViewModelcontrol the data, and how and when it gets changed.Hopefully that makes the difference between
LiveDataandMutableLiveDataclearer - they're sort of two ways of looking at the same thing, it's just one is meant for the owner of the data (it needs to be able to update/mutate the stored value, that's the whole point!) and one is meant for consumers (they get a read-only view).So to update the value, and push it to observers, you **have to have a
MutableLiveDataand you have to callsetValue()on it (orpostValueif you need to). This is especially important when yourLiveDataholds a list, because mutating that list by changing its contents won't push an update to observers. As far as theLiveDatais concerned, it's still holding the same value (a specific list object) and it has no idea if that's been changed. You have to explicitly update the value on theLiveData.So you have two options. One is you can update your list with
addor whatever, and then callsetValuewith the same list object. That will push an update, because you've "changed the value" - this is true even if you haven't updated the list at all, you're just forcing an update to theLiveData.But that can cause problems, because the last value your observers got was the same list object. If you mutate it by changing the contents, everything that's storing that list as "the previous data" will see that change, because they're looking at the same list object. If you push that "new" data with
setValue, observers will get the same list object they got last time. And if they need to compare them, they'll see they're exactly the same and "no change has happened", because they're comparing the same list object to itself.So it's usually a better idea to push a new list instead, so you're not interfering with the previous data. Meaning you should avoid using
MutableListcompletely, and do this kind of thing instead:Or if you're happy to have an empty list as your initial
LiveDatavalue (the above only provides observers with a list that has at least one Int in it):So you're using
plusto create a new list which is everything in the old one plus the new value. That way, the old list doesn't change, and anything that's hanging onto it won't get the data mysteriously changing behind its back.