Подтвердить что ты не робот

Что лучше? notifyDataSetChanged или notifyItemChanged в цикле?

Итак, у меня есть активность с RecyclerView, и я хочу изменить TextView каждого элемента в RecyclerView, нажав кнопку с onClickListener() в действии.

Мне интересно, что лучше с точки зрения производительности:

  • Используйте notifyDataSetChanged.
  • Использовать цикл с условием типа int я меньше, чем List.size(), где notifyItemChanged будет вызываться несколько раз.

В обоих случаях я создаю логическую переменную в RecyclerView Adapter, которая используется onBindViewHolder, чтобы знать, как обновить элемент. По умолчанию это значение false и после нажатия кнопки становится истинным, поэтому onBindViewHolder обновляет элемент по-разному.

Также я хотел бы знать, подходит ли этот подход вообще.

4b9b3361

Ответ 1

Если вы просто обновляете одну часть представления, используйте notifyItemRangeChanged() или notifyItemChanged() вместо notifiyDataSetChanged(). Разница здесь связана с изменениями структурных изменений и . Это находится в документации разработчиков RecyclerView.Adapter разработчиков Android. здесь.

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

Существуют два разных класса событий изменения данных, изменения элементов и структурные изменения. Изменения позиции - это когда один элемент имеет свой данные обновлены, но изменений позиции не произошло. структурная изменения, когда элементы вставлены, удалены или перемещены в пределах данных набор.

Это взято из вышеупомянутой страницы,

Если вы пишете адаптер, всегда будет более эффективно использовать более конкретные изменения событий, если можно. Полагаться на notifyDataSetChanged() в качестве последнего средства.

Итак, просто для того, чтобы прояснить использование notifyDataSetChanged() в качестве last resort, и вместо этого спросите себя, можете ли вы заново сформировать один из этих методов, и если вы можете использовать его вместо:

notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)

что имеет смысл, потому что notifyDataSetChanged() будет в значительной степени пытаться перерисовать все на основе данных и не делать никаких предыдущих предположений на нем, в то время как другие методы будут просто искать изменения. Это означает, что адаптер должен выполнять гораздо больше работы, что не требуется. Это то, что notifyDataSetChanged() делает:

Это событие не определяет, что изменило набор данных, заставляя любых наблюдателей предположить, что все существующие элементы и структура может быть недействительным. LayoutManagers будут вынуждены полностью перегруппироваться и ретранслировать все видимые виды.

Это также имеет смысл использовать инкрементный или диапазонный подход, потому что вы меняете текст, вам нужно получить каждый новый текст, и когда вы это сделаете, вы должны сообщить адаптеру, что вы его изменили. Теперь, если вы нажмете кнопку мыши и получите все новые текстовые значения, а также создайте новый список или что-то другое, назовите heavy notifyDataSetChanged().

Ответ 2

Я бы определенно назвал notifyDataSetChanged(), если все элементы данных больше недействительны. Когда вы вызываете notifyItemChanged(mPos), это эквивалентно вызову notifyItemRangeChanged(mPos, 1), и каждый раз, когда он вызывается, также вызывается requestLayout(). С другой стороны, когда вы вызываете notifyDataSetChanged() или notifyItemRangeChanged(0, mList.size()), есть только один вызов requestLayout().

Теперь ваш вопрос должен быть, что лучше, вызов notifyDataSetChanged() или notifyItemRangeChanged(0, mList.size())? Для этого у меня нет ответа.

Ответ 3

Я заметил, что notifyItemChanged(mPos) запускает onBindVieHolder для соответствующей позиции, даже если она в настоящее время не видна.

Для меня вызов его в цикле для всех элементов был более дорогостоящим, чем notifyDatasetChanged, который перерисовывал только видимые.

Поэтому будьте осторожны с большими наборами данных.