1

I have a pretty straightforward question about LiveData. I have a MutableLiveData<MutableList<Car>> and I want to update a specific field in my list, so I guess that when the field is updated, the MutableLiveData should trigger the observers but that does not happen.

So if I use this line of code my observers are not triggered.

var carList = MutableLiveData<MutableList<Car>>()
...
carList.value?.set(car.id,Car(car.id, color)) 

But if I do something like this the observers are triggered.

var carList = MutableLiveData<MutableList<Car>>()
...
var newList = carList.value
carList?.set(car.id,Car(car.id, color))
carList.value = newList 

Can please somebody explain why this happens? Is it essential to give a whole new list to the livedata to be triggered or there is something I am missing? Thank you in advance.

Konstantinos.T
  • 93
  • 1
  • 11

1 Answers1

2

If you assign a new MutableList to the wrapped value of MutableLiveData then it will notify its observers but if you add/delete any items of its wrapped value it will not notify its observers because the wrapped value has same MutableList object reference. Thus your second case is notifying where your first case does not notify. You can overcome this problem by making an extension of MutableLiveData as follows:

fun <T> MutableLiveData<MutableList<T>>.addNewItem(item: T) {
    val oldValue = this.value ?: mutableListOf()
    oldValue.add(item)
    this.value = oldValue
}

fun <T> MutableLiveData<MutableList<T>>.addNewItemAt(index: Int, item: T) {
    val oldValue = this.value ?: mutableListOf()
    oldValue.add(index, item)
    this.value = oldValue
}

fun <T> MutableLiveData<MutableList<T>>.removeItemAt(index: Int) {
    if (!this.value.isNullOrEmpty()) {
        val oldValue = this.value
        oldValue?.removeAt(index)
        this.value = oldValue
    } else {
        this.value = mutableListOf()
    }
}

Then add/remove items from your MutableLiveData like:

// Here is your car list
var carList = MutableLiveData<MutableList<Car>>()

// Add new item to your car list
carList.addNewItem(Car(car.id, color))

// Delete an item from car list at position i
carList.removeItemAt(i)

// Add new item to your car list at position i
carList.addNewItemAt(i, Car(car.id, color))
Md. Yamin Mollah
  • 1,609
  • 13
  • 26
  • 2
    I see ...So it is not possible to trigger the observers just by update a field in the already existed list... – Konstantinos.T May 16 '20 at 19:49
  • @Konstantinos.T No, it is not possible but if `Android Authority` make it possible in future then we can do it in future. Thank you – Md. Yamin Mollah May 17 '20 at 04:48
  • Can't we just use something like `var carList = MutableList()` instead of `var carList = MutableLiveData>()` – Kamil Oct 23 '22 at 14:43
  • Oh, I see. `MutableList` is not designed for `LiveData` at all. It is just a thread-safe List. Thank you for sharing simple implementation of something that I would call `LiveDataCollection` – Kamil Oct 23 '22 at 14:47
  • @Kamil Yeah! you already got it brother. – Md. Yamin Mollah Oct 24 '22 at 04:16