35

I'm using LiveData and ViewModel from the architecture components in my app.

I have a list of items that is paginated, I load more as the user scrolls down. The result of the query is stored in a

MutableLiveData<List<SearchResult>>

When I do the initial load and set the variable to a new list, it triggers a callback on the binding adapter that loads the data into the recyclerview.

However, when I load the 2nd page and I add the additional items to the list, the callback is not triggered. However, if I replace the list with a new list containing both the old and new items, the callback triggers.

Is it possible to have LiveData notify its observers when the backing list is updated, not only when the LiveData object is updated?

This does not work (ignoring the null checks):

val results = MutableLiveData<MutableList<SearchResult>>()

/* later */

results.value.addAll(newResults)

This works:

val results = MutableLiveData<MutableList<SearchResult>>()

/* later */

val list = mutableListOf<SearchResult>()
list.addAll(results.value)
list.addAll(newResults)
results.value = list
Neil Turner
  • 2,712
  • 2
  • 18
  • 37
Francesc
  • 25,014
  • 10
  • 66
  • 84
  • The only possible way I know is to set the whole list so you notify the observers. A trick which is a bit nicer can be found here: https://stackoverflow.com/questions/48020377/livedata-update-on-object-field-change/48194074#48194074 – woodii Mar 13 '18 at 09:17
  • 1
    Thanks, that's mostly a work-around, but I'll give that a try. – Francesc Mar 13 '18 at 15:12

2 Answers2

34

I think the extension is a bit nicer.

operator fun <T> MutableLiveData<ArrayList<T>>.plusAssign(values: List<T>) {
    val value = this.value ?: arrayListOf()
    value.addAll(values)
    this.value = value
}

Usage:

list += anotherList;
Samnang CHEA
  • 643
  • 7
  • 10
12

According to MutableLiveData, you need to use postValue or setValue in order to trigger the observers.

Alexander Pacha
  • 9,187
  • 3
  • 68
  • 108
Shynline
  • 1,497
  • 1
  • 13
  • 18