Ответ
Были сложности с оптимизацией RecyclerView для списка с тысячами элементов и тяжелыми изображениями. Проблема была в лагах при скролле. Решил через:
- Пагинацию с
Paging3 - Оптимизацию
ViewHolder(минимальная логика вonBind) - Библиотеку
Coilдля асинхронной загрузки и кеширования картинок - Дифф-утилиты для эффективных обновлений
Пример:
val adapter = MyAdapter(diffCallback)
recyclerView.adapter = adapter.withLoadStateFooter(LoadingFooter())
viewModel.pagingData.observe(this) { pagingData ->
adapter.submitData(lifecycle, pagingData)
}
Другая проблема — утечки памяти в ViewModel из-за неправильной работы с LiveData. Исправил через viewModelScope и repeatOnLifecycle.
Ответ 18+ 🔞
А, ну это классика, блядь! Каждый, кто за RecyclerView брался, через это проходил. Ты скролишь, а он дергается, как будто по кочкам едешь, ёпта. Картинки грузятся — всё встаёт колом, волнение ебать, терпения ноль ебать.
Ну, ты в целом правильный путь выбрал, чувак. Пагинация через Paging3 — это сейчас святое, иначе овердохуища элементов в памяти — и привет, OutOfMemoryError, накрылся медным тазом твой список.
Главное, что ты Coil подключил, а не какой-нибудь старый Picasso или самописные AsyncTask-и, которые уже как будто на дворе 2002-й год. Coil — это пизда рулю, он сам и кеширует, и в нужном размере загружает, и отменяет запросы, если вьюха за экраном ушла. Красота.
А вот с LiveData в ViewModel — это тонкий лёд, чувак. Очень тонкий. Ты там подписался из активити или фрагмента, а потом этот фрагмент нахуй уничтожился, а подписка-то жива, и ViewModel тянет за собой весь контекст в мир иной. Получается утечка, память течёт, как вода из дырявого ведра. Сам от себя охуеешь, когда в профиле увидшь.
Правильно, что через repeatOnLifecycle поправил. Это сейчас модно-молодёжно и правильно. Раньше-то все в onCreate подписывались и в onDestroy отписывались, а если забудешь — пиши пропало. А сейчас взял и обернул:
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.myLiveData.collect { data ->
// Обновляем UI
}
}
}
И всё, блядь! Само отпишется, когда стейт не STARTED. Умно. viewModelScope в самой вьюмодели — тоже верно, чтобы корутины не висели, если вьюмодель зачистили.
Дифф-утилиты — это вообще магия. Без них каждый раз весь список заново перерисовывался, как будто его мартышлюшка собрала. А с ними система видит: "О, а этот хуй с горы не изменился, его можно не трогать". И перерисовывает только то, что реально поменялось. Скорость скролла вырастает в разы, удивление пиздец.
Короче, молодец, что не поленился и всё по уму сделал. А то некоторые пытаются костыли на костылях лепить, а потом удивляются, почему приложение сосалка и бздун.