I am using DiffUtil.ItemCallback along with ListAdapter to update RecyclerView.
It's working pretty well but there is something that bothering me with it's behaviour.
According to the documentation, the areContentsTheSame
method should be called only if areItemsTheSame
returns true
.
From the documentation:
This method is called only if areItemsTheSame(int, int) returns true for these items.
However, in my case when updating the list with a new list, like this:
adapter.submitList(items.toMutableList())
The DiffUtil.ItemCallback do triggered but even when areItemsTheSame
returns true
it wont call areContentTheSame
right away (as expected?) but instead, areItemsTheSame
called again and again on different pair of objects, (I've used debugger with breakpoints there).
After areItemsTheSame
called a few times and return true, finally it do calls areContentTheSame
and sometimes, I see that the objects that delivered to areContentTheSame
actually not the same!! and has different id!! this means that areContentTheSame
shouldn't even called on these pair!!
This is how my DiffUtilCallback is implemented:
class AppDiffCallback : DiffUtil.ItemCallback<Item?>() {
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
Timber.i("areItemsTheSame: called..")
if (oldItem.getItemType() == newItem.getItemType()) {
Timber.i("areItemsTheSame: done true..")
return true
}
Timber.w("areItemsTheSame: done false..")
return false
}
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
Timber.i("areContentsTheSame: called")
if(oldItem.getItemType() != newItem.getItemType()){
Timber.w("areContentsTheSame: itemsNotTheSame WTF???}")
return false
}
return when (oldItem.getItemType()) {
Item.HEADER -> checkHeaderContent(oldItem = oldItem as ItemHeader, newItem = newItem as ItemHeader)
Item.ITEM_ACTION -> checkItemContent(oldItem = oldItem as ItemAction, newItem = newItem as ItemAction)
else -> false
}
}
private fun checkHeaderContent(oldItem: ItemHeader, newItem:
ItemHeader): Boolean {
val itemContentTheSame = oldItem.date.toDate().time ==
newItem.date.toDate().time
return itemContentTheSame
}
private fun checkItemContent(oldItem: ItemAction, newItem: ItemAction): Boolean {
val itemContentTheSame = oldItem.action == newItem.action
return itemContentTheSame
}
}
In addition, when running this, in the logcat I see many calls to areItemsTheSame
with true
but very few areContentTheSame
Is this an expected behaviour?