Главная » Хабрахабр » О чем все-таки говорит developer.android.com про RecyclerView

О чем все-таки говорит developer.android.com про RecyclerView

На написание статьи меня подтолкнул этот пост (а точнее, то чувство резкого локального повышения температуры в районе… хм, поясницы, обычно возникающее, когда в интернете кто-то неправ). Приветствую вас, уважаемые хабражители!

Полностью согласен, что "между жизненным циклом активности и работой RecyclerView есть нечто общее" – это "нечто" – необходимость понимать, что мы делаем и зачем. Начнем с самого начала. А невыполнение этих двух необходимостей, как и сон разума, рождает монстров. И читать документацию. Только вот с тем, как предлагает с этими монстрами бороться предыдущий автор, я категорически не согласен.

Рассмотрим 2 условия.

Условие № раз

Делают это обычно в симметричных функциях – присоединяем в onViewAttachedToWindow, убираем в onViewDetachedFromWindow. Если вы где-то навешиваете listener, то где-то в другом месте вы должны его отсоединять. Этот вызов не симметричный, он может вызываться несколько раз в зависимости от разных условий. Присоединяем в onBindViewHolder… Не присоединяем в onBindViewHolder. Не надо усложнять себе жизнь.

Так делать нельзя. Если же вам, как и автору исходной статьи приходит в голову мысль: "Но есть случаи, когда… в слушателе необходимо учитывать позицию элемента в списке, доступ к которой есть в методе onBindViewHolder() и отсутствует в onViewAttachedToWindow()", то гоните эту мысль прочь. Как сказано в документации, этот метод не будет вызван, если изменилась только позиция элемента, но не его содержимое, поэтому мы рискуем получить в нашем слушателе неправильную позицию. Даже если очень хочется. Используйте getAdapterPosition.

Условие № два

Не надо усложнять себе жизнь еще больше. RecyclerView – штука довольная сложная. Если вы не занимаетесь оптимизацией производительности, вам не должно быть важно, попал этот элемент в общий пул или нет.

Результат

При соблюдении этих двух условий вам вряд ли понадобится изобретать велосипед в виде флага типа viewWasRecycled.

Что происходит?

Во-первых, надо учитывать, что есть 2 "хранилища" – кэш и пул. Что вообще может происходить с элементом в RecyclerView? метод onBindViewHolder вызван не будет). В кэш элемент попадает, если он ушел за границы экрана, но в любое время может вернуться снова – при этом даже не произойдет перепривязки этого элемента (т.е. Восстановленный из пула элемент будет перепривязан (потому что скорее всего его позиция изменилась), и мы получим вызов onBindViewHolder. Если кэш заполнился, или по какой-то другой причине RecyclerView решил, что этот элемент нам в ближайшее время не понадобится, он отправится в пул (вот здесь и будет вызван onViewRecycled). А вот если элемент ушел и из пула, тогда новый элемент пройдет через весь цикл – onCreateViewHolder, onBindViewHolder, onViewAttachedToWindow.

Итого, у нас есть 3 варианта развития событий:

  • элемента раньше не было: создаем, привязываем, присоединяем;
  • элемент был в пуле: привязываем, присоединяем;
  • элемент был в кэше: просто присоединяем.

Где и как?

Что и на каких этапах лучше делать с элементом?

  • onCreateViewHolder. Создаем, хм, ViewHolder. Не надо здесь привязывать listener, заполнять контентом и т.д. Достаточно просто определить, какой тип нам нужен и создать его.
  • onBindViewHolder. Выполняем фактическую привязку контента – текст, картинки. Параметр position можно использовать только в самом методе – не сохраняем его, не отправляем в замыкания, помним, что этот метод будет вызван еще раз в том случае, если изменились данные (и не будет, если поменялось только положение). Listener я бы тоже не стал здесь навешивать – из соображений симметрии.
  • onViewAttachedToWindow. Элемент будет сейчас виден на экране, пользователь сможет с ним взаимодействовать – хороший момент, чтобы присоединить listener. Помним, что если внутри него нам нужна позиция элемента, то получаем ее через getAdapterPosition.
  • onViewDetachedFromWindow. Элемент не будет отображаться на экране. Пользователь не сможет с ним взаимодействовать. Убираем listener.
  • onViewRecycled. Элемент отправляется в ад пул. Здесь можно освободить тяжелые ресурсы (закэшированные картинки, например). Если элемент и будет переиспользован – то, скорее всего, для другой позиции.

Надеюсь, ничего не забыл и не перепутал, но если что – тыкайте носом, не стесняйтесь. Вот вроде бы и всё.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Иди-ка ты сам на… или правила общения в команде

Пост-ответ на статью "Иди-ка ты на !@# со своей "токсичностью"". Если бы я последовал советам из этой статьи, мне достаточно было бы проявить эмоцию и сказать автору "Иди-ка ты сам на на ..., ты ничего не понимаешь!". Поэтому давайте разберем ...

[Перевод] Сделал редизайн — потерял миллиард

Исследуем эпичные провалы редизайна и мотаем на ус. Менеджер по продукту заходит в отдел дизайна и заказывает редизайн сайта. «Наш сайт выглядит таким старым! У всех наших конкурентов есть более яркие сайты. Давайте перепроектируем его. Кнопки с разноцветными тенями — ...