RecyclerView внутри RecyclerView, сбой приложения из-за большого потребления памяти

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

Например, без раскрытия:

введите описание изображения здесь

и расширен:

введите описание изображения здесь

Макет внешнего элемента recyclerView содержит только textView, флажок и невидимый recyclerview, который становится видимым при щелчке по элементу.

Я объявил внешний адаптер следующим образом:

photosVideosAdapter = new PhotosVideosAdapter(getContext(),new ArrayList<PhoneAlbum>());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(photosVideosAdapter);

Вот onBindViewHolder внешнего адаптера:

holder.tvFolder.setText(phoneAlbums.get(position).getName());
ArrayList<PhonePhoto> phonePhotos = phoneAlbums.get(position).getAlbumPhotos();
InnerAdapter innerAdapter = new InnerAdapter(context, phonePhotos);
holder.innerRecyclerView.setHasFixedSize(true);
holder.innerRecyclerView.setLayoutManager(new GridLayoutManager(context,3));
holder.innerRecyclerView.setAdapter(innerAdapter);
.... OnClickMethod to toggle visibility of innerRecyclerView

И onBindViewHolder для внутреннего адаптера:

Glide.with(context)
        .load(phonePhotos.get(position).getPhotoUri())
        .override(200,200)
        .into(holder.imgThumbnail);

Проблема в том, что если внутренний recyclerView содержит более 200 элементов, приложение вылетает из-за большого использования памяти. Но, как видите, я использую скольжение для загрузки изображений, а также RecyclerView не должен создавать все представления сразу. Но я вижу, что внутренний RecyclerView создает все представления элементов одновременно, что приводит к сбою приложения.

Как я могу исправить эту проблему? Любая помощь будет оценена по достоинству.


person Jazib Khan    schedule 12.07.2020    source источник
comment
Проблема в том, что внутренний recyclerView загружает все представления сразу. Итак, если внутренний recyclerView имеет 1000 изображений, все изображения загружаются одновременно, что не является тем, что должен делать recyclerView.   -  person Jazib Khan    schedule 12.07.2020


Ответы (3)


Поверьте мне, не используйте recyclerview внутри recyclerview. У меня была аналогичная ситуация в моем текущем приложении, где мой коллега построил решение, используя вложенный recyclerview.

Я переписал всю логику, используя вставку и удаление с анимацией и несколькими типами просмотра. Для управления им потребуется дополнительный код. Но результат был бы вполне удовлетворительным.

Фактически, я использовал ту же логику и в iOS collectionview. Приложение на обеих платформах работает.

person Sandeep Dhull    schedule 12.07.2020

Попробуйте добавить это в свой manifest.xml

        android:largeHeap="true"

person quadri adedayo    schedule 12.07.2020
comment
Проблема не в увеличении размера кучи. Проблема в том, что внутреннее представление ресайклера создает все представления сразу, поэтому, если в альбоме 4000 фотографий, он создаст все 4000 представлений одновременно. - person Jazib Khan; 12.07.2020

Скорее всего, у вас будет много памяти, потому что вы извлекли сразу все фотографии из альбома со строкой:

ArrayList<PhonePhoto> phonePhotos = phoneAlbums.get(position).getAlbumPhotos();

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

Один из способов исправить это - загрузить предварительный просмотр фотографий с более низким разрешением в оперативную память, и как только фотография будет отображаться в RecyclerView, вы можете загрузить фотографию с полным разрешением.

person Anirudh    schedule 12.07.2020
comment
Один из способов проверить, действительно ли это основная причина вашей проблемы, - это закомментировать весь код, касающийся отображения изображений в RecylcerView, и посмотреть, остается ли использование памяти очень высоким. - person Anirudh; 12.07.2020
comment
PhonePhoto содержит только URI изображений, а все URI изображения уже сохранены в ArrayList. - person Jazib Khan; 12.07.2020
comment
Проблема в том, что внутреннее представление ресайклера загружает все представления сразу. Итак, если внутреннее представление ресайклера имеет 1000 изображений, все изображения загружаются одновременно, что не является тем, что должен делать recyclerView. - person Jazib Khan; 12.07.2020
comment
Вы пробовали регистрировать, что layoutManager.getChildCount (); возвращает, это должно быть количество просмотров, которые в настоящее время загружены - person Anirudh; 12.07.2020
comment
Для innerRecyclerView это равно количеству изображений. - person Jazib Khan; 12.07.2020
comment
Другой ответ говорит, что это может иметь какое-то отношение к вашему макету - person Anirudh; 12.07.2020