При обновлении RecycleView с использованием DiffUtils изображения ViewView мерцают - PullRequest
0 голосов
/ 11 апреля 2020

В адаптере моего RecyclewView я использую DiffUtils для обновления только тех элементов, которые были изменены. Делая это, я заметил, что ImageViews мерцают при каждом обновлении, и во время отладки я обнаружил, что метод onCreateViewHolder моего адаптера вызывается каждый раз, когда я обновляю данные, поэтому держатели не используются повторно, как они должны. Когда я избавляюсь от DiffUtil и использую простые notifyDataSetChanged мерцающие исчезает. Так почему же воссоздаются эти ViewHolders и как я могу это исправить?

Вот мой обратный вызов DiffUtil:

class MyDiffUtilCallback(val newList: List<Item>, val oldList: List<Item>) : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
    return newList[newItemPosition].id == oldList[oldItemPosition].id
}

override fun getOldListSize(): Int = oldList.size

override fun getNewListSize(): Int = newList.size

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
    return newList[newItemPosition] == oldList[oldItemPosition]
}

}

И как я обновляю свой адаптер:

fun updateItems(items: List<Item>) {
    val diff = DiffUtil.calculateDiff(MyDiffUtilCallback(items, this.items))
    this.items = items
    diff.dispatchUpdatesTo(this)
}

РЕДАКТИРОВАТЬ: Я рассмотрел проблему еще несколько раз и заметил, что при использовании notifyDataSetChanged также создаются воссозданные видоискатели, я всегда думал, что при обновлении видоискатели используются повторно, но я думаю, Это не относится к делу. В любом случае мерцание изображения все еще видно только при использовании DiffUtil, а не notifyDataSetChanged, и я не знаю, почему

1 Ответ

0 голосов
/ 11 апреля 2020

В вашем коде вместо кода ниже

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): 
Boolean {
    return newList[newItemPosition] == oldList[oldItemPosition]
}

Используйте это.

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): 
Boolean {
    return newList[newItemPosition].id == oldList[oldItemPosition].id
}

, потому что, когда вы сравниваете два объекта, они сравниваются по ссылке на память, я думаю, что в этом случае, пока При подготовке нового списка вы не используете одни и те же объекты старых списков, поэтому вы должны проверить, равны ли они, используя их уникальный идентификатор вашей пользовательской модели данных «Элемент». Но в вашем случае он снова вызывает onCreateViewHolder, здесь этого не должно быть, попробуйте этот подход один раз, и, кстати, используете ли вы адаптер, поддерживающий несколько типов элементов, если да, это может быть возможно, так как в измененном списке вы находитесь получение новых типов элементов, которые еще не были созданы, если у нас не было этих типов элементов в предыдущем старом списке.

...