Just FYI, I'm not exactly looking for a 'fix' but for an explanation and a discussion that might help understand a little bit more how seemingly silly things like these work.
I was working on this bigger project when I realized that somewhere, a certain list wasn't being updated correctly. Looking a little closer, the items, were correctly being modified, and if you 'scrolled away' and back, the item's information would be displayed correctly.
I stumbled upon this article: ListAdapter not updating item in RecyclerView
But the difference here, is that in fact, DiffUtils was being called, but somehow the newItem
and oldItem
were the same! I understand that the library assumes you are using Room or any other ORM which offers a new async list every time it gets updated, but here's the thing. If I submit the list "naively" DiffUtils is not even called. But, if I submit the list as list.toMutableList()
like some suggest then, DiffUtils IS called, but somehow the items, new and old, are already the same, hence, nothing gets updated at that moment (verified this by placing breakpoints inside areContentsTheSame
).
I leave you here the relevant snippets and a link to a test project I created just so I could encapsulate the behavior and test it separately from everything else.
The Fragment - just calling the submitList
viewModel.items.observe(viewLifecycleOwner) {
adapter.submitList(it.toMutableList())
}
ViewModel
private val _items = MutableLiveData<List<SimpleItem>>()
val items: LiveData<List<SimpleItem>>
get() = _items
init {
_items.value = ItemsRepo.getItems()
}
fun onItemClick(itemId: Int) {
ItemsRepo.addItemCount(itemId)
_items.value = ItemsRepo.getItems()
}
The "Repo" I create some data object ItemsRepo {
private var items = mutableListOf(
SimpleItem(1),
SimpleItem(2),
SimpleItem(3),
SimpleItem(4),
SimpleItem(5)
)
fun getItems(): List<SimpleItem> {
return items
}
fun addItemCount(itemId: Int) {
items.find { it.itemId == itemId }?.let {
it.itemClickCount += 1
}
}
The GitHub repo: https://github.com/ellasaro/ListAdapterTest
Cheers!
List
fromgetList()
worked perfectly. My Adapter's click handler was already returning the item'sid
so I searched the index of the element and swapped it with a modified copy. I now understand (sort of) the cause of the problem. Thanks for your insight! – Linalinacre