Как использовать ContentObserver с RecyclerView?

С ListView у нас был хороший собственный шаблон для отображения некоторых данных из db в список:

DB -> ContentProvider -> CursorLoader -> CursorAdapter -> ListView

Этот подход был хорош с точки зрения разделения слоев данных, производительности и автоматического обновления данных. Но этот шаблон не очень подходит для нового RecyclerView. Есть несколько подходов к имитации старого поведения:

Использование recyclerview с базой данных

Но есть проблема с использованием старого стиля notifyDataSetChanged с RecyclerView. Он не может использовать функции ItemAnimator, теряет позицию прокрутки и просто неэффективен.

Итак, как мы можем извлечь выгоду из детальных уведомлений об изменениях при использовании БД, завернутой в ContentProvider? Cursor является статическим, и чтобы получить из него новые данные, нам нужно получить новый Cursor. Итак, похоже, нам понадобится пользовательский промежуточный слой данных, который объединит данные из курсоров и предоставит List сущностей RecyclerView.Adapter. Кроме того, нам придется вручную сопоставлять события ContentObserver onChange() с уведомлениями RecyclerView. Это также означает, что нам придется избавиться от CursorLoader. Это невероятный объем работы для такой простой задачи.

Есть ли лучшее решение?


person rudzha    schedule 24.04.2015    source источник


Ответы (1)


Вы можете использовать класс DiffUtils для вычисления различий между старым и новым курсором.

При его использовании вам просто нужно реализовать два метода:

  • areItemsTheSame() чтобы узнать, представляют ли два элемента один и тот же логический элемент (даже если их содержимое различно). Обычно вы основываете ответ на идентифицирующем поле вашего элемента;
  • areContentsTheSame() чтобы узнать, имеют ли два элемента, представляющие один и тот же логический элемент, неизмененный контент.

Как только различия будут вычислены, вы можете просто применить их к своему адаптеру, и он автоматически вызовет notifyItemChanged(), notifyItemInserted() или notifyItemRemoved() соответственно.

person XGouchet    schedule 07.11.2016