Я использую DiffUtil.ItemCallback вместе с ListAdapter для обновления RecyclerView.
Это работает довольно хорошо, но есть кое-что, что беспокоит меня своим поведением.
Согласно документации, метод areContentsTheSame
следует вызывать только в том случае, если areItemsTheSame
возвращает true
.
Из документации:
Этот метод вызывается, только если areItemsTheSame (int, int) возвращает true для этих элементов.
Однако в моемслучай обновления списка новым списком, например:
adapter.submitList(items.toMutableList())
DiffUtil.ItemCallback срабатывает, но даже когда areItemsTheSame
возвращает true
, он сразу не вызовет areContentTheSame
(как и ожидалось?) но вместо этого areItemsTheSame
вызывается снова и снова на разных парах объектов (я использовал там отладчик с точками останова).После того, как areItemsTheSame
вызвали несколько раз и вернули true, наконец-то он вызывает areContentTheSame
, и иногда я вижу, что объекты, доставленные на areContentTheSame
, на самом деле не совпадают !!и имеет другой идентификатор!это означает, что areContentTheSame
не следует даже вызывать эти пары !!
Вот как реализован мой DiffUtilCallback:
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
}
}
Кроме того, при запуске этого сообщения в logcat я вижу много вызовов areItemsTheSame
с true
, но очень мало areContentTheSame
Это ожидаемое поведение?