Как использовать ContentObserver с RecyclerView?
С ListView
у нас был хороший собственный шаблон для сопоставления некоторых данных из db в список:
DB
→ ContentProvider
→ CursorLoader
→ CursorAdapter
→ ListView
Этот подход был хорош с точки зрения разделения данных, производительности и автоматических обновлений данных. Но этот шаблон не подходит для нового RecyclerView
. Существуют некоторые подходы к воспроизведению старого поведения:
Использование recyclerview с базой данных
Но есть проблема с использованием старого стиля notifyDataSetChanged
с RecyclerView
. Он не может использовать функции ItemAnimator, он теряет положение прокрутки, и он просто неэффективен.
Итак, как мы можем извлечь выгоду из мелкомасштабных уведомлений об изменениях при использовании DB, завернутых в ContentProvider
? Cursor
является статическим, и для получения новых данных из него нам нужно получить новый Cursor
. Таким образом, нам кажется, что нам понадобится пользовательский промежуточный уровень данных, который объединит данные из Cursors и выведет List
объектов в RecyclerView.Adapter
. Кроме того, нам придется вручную сопоставлять события ContentObserver
onChange()
с уведомлениями RecyclerView. Это также означает, что нам придется избавиться от CursorLoader. Это невероятная работа для такой основной задачи.
Есть ли лучшее решение?
Ответы
Ответ 1
Вы можете использовать класс DiffUtils для вычисления различий между старым и новым курсором.
При использовании его вам просто нужно реализовать два метода:
-
areItemsTheSame()
, чтобы узнать, представляют ли два элемента один и тот же логический элемент (даже если содержимое отличается). Обычно вы должны основывать ответ на поле идентификации вашего элемента;
-
areContentsTheSame()
, чтобы знать, имеют ли два элемента, представляющие один и тот же логический элемент, немодифицированный контент.
После вычисления различий вы можете просто применить его к вашему адаптеру, и он автоматически вызовет notifyItemChanged()
, notifyItemInserted()
или notifyItemRemoved()
.