Итак, после нескольких часов отладки, вот что я узнал.
- Список изначально загружен с данными
- обновления выполняются для текущих данных, например, приращение
item.quantity = 2
- После получения новых данных (через поиск или фильтры) onBindViewHolder НЕ вызывается, если itemsAretheSame или ContentsAreThemSame , поэтому нет необходимости обновлять представление. На данный момент все в порядке.
Однако кажется, что currentList был обновлен с учетом вновь полученных данных без обязательного обновления представления ... Теперь, когда вызывается notifyItemChanged
, запускается onBindViewHolder :
Вот как мой onBindViewHolder
равен
override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
getItem(position)
дает вам элемент из текущего списка, который был обновлен, и количество возвращается к значению по умолчанию 0.
Решение
Переопределите приведенную ниже функцию RecyclerView.Adapter
override fun onBindViewHolder(
holder: ViewHolder<ProductEntity>,
pos: Int,
payloads: MutableList<Any>
) {
if(payloads.isEmpty()) return super.onBindViewHolder(holder, pos, payloads)
val product = getItem(pos)?: return
payloads.forEach {
val oldProduct = it as ProductEntity
if(product.item.id == oldProduct.item.id){
product.quauntity = oldProduct.quantity
}
}
}
Полезная нагрузка должна включать частичные старые данные, которые можно использовать для обновления новых данные ..
По документации
* The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or
* {@link #notifyItemRangeChanged(int, int, Object)}. If the payloads list is not empty,
* the ViewHolder is currently bound to old data and Adapter may run an efficient partial
* update using the payload info. If the payload is empty, Adapter must run a full bind.
* Adapter should not assume that the payload passed in notify methods will be received by
* onBindViewHolder(). For example when the view is not attached to the screen, the
* payload in notifyItemChange() will be simply dropped.