Работали ли вы с ListAdapter в Android
Что проверяют
Понимаете ли вы, зачем список обновляется через вычисленную разницу, а не полным notifyDataSetChanged, и знаете ли ограничения ListAdapter. Базовый вопрос про RecyclerView: по ответу видно, писали вы адаптеры сами или копировали с готового экрана.
Как отвечать
ListAdapter это RecyclerView.Adapter со встроенным AsyncListDiffer. Вы отдаёте новый список в submitList, разница считается в фоновом потоке, а точечные уведомления об изменениях адаптер рассылает сам. Поэтому работают анимации вставки и удаления, а экран не мигает целиком.
Разницу описывает DiffUtil.ItemCallback: areItemsTheSame отвечает на вопрос, тот ли это элемент, обычно сравнением по идентификатору, areContentsTheSame на вопрос, изменилось ли содержимое. Третий метод, getChangePayload, возвращает описание частичного изменения, и тогда холдер обновляет одно поле вместо полной перепривязки.
Обязательно скажите про неизменяемость: список должен быть новым объектом. Если поменять тот же экземпляр и передать его снова, сравниваться будет список сам с собой, и обновление не произойдёт. У submitList есть версия с колбэком, который вызывается после применения изменений, туда удобно вешать прокрутку к нужной позиции.
Полезно обозначить границы: постраничная загрузка это PagingDataAdapter, а в Compose роль идентификатора из DiffUtil играет параметр key у элемента списка.
Где спотыкаются
Меняют список на месте и вызывают submitList с той же ссылкой. Экран не обновляется, разработчик добавляет сверху notifyDataSetChanged и теряет весь смысл адаптера вместе с анимациями.
Второе: пишут areContentsTheSame через сравнение объектов у класса без корректного equals. У обычного класса сравниваются ссылки, и разница считает изменившимися все элементы, а с полем-массивом бывает наоборот, изменение остаётся незамеченным.
Третье: возвращают идентичность по позиции в списке. После вставки в начало все элементы сдвигаются, адаптер решает, что изменилось всё, анимации врут, а состояние выделения переезжает на чужую строку.