DiffUtil.Callback not working as expected
Asked Answered
I

0

8

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?

Insatiate answered 17/6, 2019 at 9:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.