У меня есть список статей, и когда на сервере появляются новые статьи, я отображаю кнопку, информирующую об этом пользователя. Когда пользователь нажимает эту кнопку, я хочу загрузить новейшие статьи и добавить их в начало списка. Пока загружаются новые статьи, я отображаю элементы-заполнители (просматриваем скелеты элемента статьи без данных) для них в RecyclerView и прокручиваю вверх по списку, чтобы были видны новейшие статьи.
Проблема в том, что когда новые статьи извлекаются и заменяют заполнители, RecyclerView не прокручивается вверх, а вместо этого прокручивается на предыдущих данных, и мне приходится вручную прокручиваться, чтобы быть в верхней части списка.
Возможно, это что-то сделать с попыткой RecyclerView сохранить прокрутку пользователя там, где он был раньше, но в этом случае пользователя здесь не было.
Временное решение: либо отключить анимацию в RecyclerView, либо не выполнять различие данных, используя DiffUtil
, но вызывать notifyDatasetChanged
.
Я пошел со вторым подходом, потому что я хочу иметь анимации
Я создал демонстрационный репозиторий , демонстрирующий эту проблему. Существует два вида деятельности: один с ванильными RecyclerView
и RecyclerView.Adapter
, а второй с использованием библиотеки epoxy .
Код для всего класса довольно сложный, и я не уверен, какой из них более актуален, поэтому так выглядит Activity
. Она симуляция загрузки новых статей
private fun simulateFetchNewArticles() {
scope.launch {
val newArticlesCount = 10
adapter.items = (0 until newArticlesCount).map { Item.Placeholder("Placeholder $it") } + adapter.items
delay(100)
recyclerView.smoothScrollToPosition(0)
delay(5000)
// Uncomment for workaround fix
// adapter.items = emptyList()
adapter.items = (0 until newArticlesCount).map { Item.Article("New article $it") } + adapter.items.drop(newArticlesCount)
}
}