Как определить, какую картинку загрузить в конкретный ImageView при асинхронной загрузке в списке?
Что проверяют
Понимаете ли вы, как RecyclerView переиспользует ViewHolder и почему из-за этого асинхронная загрузка показывает чужую картинку. Следом спрашивают, что под капотом делает Glide или Coil и как решить задачу без библиотеки.
Как отвечать
Опишите проблему: загрузка для позиции 5 стартовала, пользователь пролистал, тот же ImageView уже привязан к позиции 25, а старый запрос дописывает картинку поверх. Решение складывается из трёх частей:
- отмена прежнего запроса: Glide хранит текущий запрос в теге самого
ImageView, и новыйGlide.with(itemView).load(url).into(imageView)отменяет предыдущий. Coil черезimageView.load(url)делает то же и умеетdispose(); - сброс в
onBindViewHolder: если у элемента нет картинки, всё равно вызывайтеGlide.with(itemView).clear(imageView)или ставьте плейсхолдер. Иначе останется изображение от прошлой позиции; - своя загрузка: перед стартом кладёте в
imageView.tagURL или id элемента, а в колбэке сравниваете, совпадает ли тег. С корутинами надёжнее хранитьJobв холдере и отменять его вonViewRecycled()и перед новым биндом.
Дополнительно: не захватывайте position в лямбду, для кликов берите bindingAdapterPosition. Контекст для загрузки выбирайте по жизненному циклу: Glide.with(fragment) сам остановит запросы, когда экран уйдёт. Кэш в памяти и на диске библиотеки ведут сами, в ручном варианте нужен LruCache с размером от доступной памяти.
В Compose задача почти исчезает: AsyncImage из Coil привязан к модели, а элементам LazyColumn стоит задавать key, чтобы состояние не переезжало между строками.
Где спотыкаются
Пишут загрузку только внутри if (url != null) без ветки else. Пустые элементы при прокрутке показывают картинки соседей.
Сверяют по позиции, а не по идентификатору элемента. После вставки или удаления позиции сдвигаются, и проверка пропускает не ту картинку.
Грузят через Glide.with(applicationContext). Запросы переживают экран и продолжают тратить сеть и память после ухода пользователя.