#flutter
Вопрос:
У меня в приложении есть фотогалерея, которая использует a PageView
для отображения одного изображения с высоким разрешением на странице.
Быстро просматривая галерею, я могу надежно завершить работу своего приложения. В моем случае на iPhone 12 Pro 27-е изображение убивает его на 2,8 ГБ памяти:
* thread #12, name = 'io.flutter.1.io', stop reason = EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=2867 MB, unused=0x0)
frame #0: 0x00000001de32c64c libsystem_platform.dylib`_platform_memmove 76
libsystem_platform.dylib`_platform_memmove:
-> 0x1de32c64c < 76>: stnp q0, q1, [x3]
0x1de32c650 < 80>: add x3, x3, #0x20 ; =0x20
0x1de32c654 < 84>: ldnp q0, q1, [x1]
0x1de32c658 < 88>: add x1, x1, #0x20 ; =0x20
Target 0: (Runner) stopped.
Выглядит загадочно, но ясно говорит о том, что вся доступная память израсходована.
Некоторые изображения имеют наложение, например переключатель или поле формы, как часть страницы. Я понял, что их состояние сохраняется, пока я прокручиваю назад и вперед. Поскольку я использую PageView.builder
конструктор, я на самом деле ожидал, что страницы будут удалены, и при прокрутке в памяти останется только фиксированное окно страниц вокруг текущей страницы. Когда я удаляюсь из галереи после прокрутки 20 изображений (чтобы весь просмотр страницы был удален) и возвращаюсь в галерею, я могу провести еще 20 изображений и повторить это без сбоев. Так что, похоже, избавление от PageView
этого очищает память.
Как я могу принудительно удалить страницы?
Google дает мне много вопросов и ответов о том, как поддерживать страницы в PageView
живом состоянии, и это подтверждает мое ожидание, что просмотр страниц должен распоряжаться ресурсами, если я не скажу ему явно что-то другое.
Краткие сведения:
- Я использую
PageView.builder
- Состояние страницы, по-видимому, сохраняется для всех страниц по умолчанию
- Приложение выходит из строя после отображения x страниц
Вот мой код просмотра страниц для справки:
PageView.builder(
clipBehavior: Clip.hardEdge,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) => GalleryCustomChild(image: viewModel.images[index]),
itemCount: viewModel.images.length,
controller: viewModel.pageController,
)
class GalleryCustomChild extends StatelessWidget {
final ImageData image;
const GalleryCustomChild({required this.image, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return PhotoView(
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered,
initialScale: PhotoViewComputedScale.contained,
backgroundDecoration: const BoxDecoration(color: Colors.black),
imageProvider: FileImage(
File(image.filePath),
),
);
}
}
Комментарии:
1. Привет, я думаю, вы не избавляетесь от своего pageViewController. Пожалуйста, попробуйте избавиться от контроллера, переопределив метод dispose ().
2. Спасибо вам, ребята, за вклад 🙂 Я попробовал и то, и другое, но, к сожалению, безрезультатно. Размер кэшированного изображения печатается как 0 или какое-то разумное значение, но сбой все равно произойдет.
3. Есть какие-нибудь новости по этому поводу? Я сталкиваюсь с точно такой же проблемой. Я показываю изображения в виджете просмотра страниц. Я могу прокрутить около 30 полноразмерных изображений (от 1 до 2 МБ) на своем iPhone 11 pro, прежде чем приложение внезапно выйдет из строя. На странице памяти в инструментах разработки Dart я вижу, что использование памяти продолжает увеличиваться при листании страниц. Для меня, однако, когда я удаляю виджет просмотра страниц, скажем, после 25 пролистываний без сбоев, и продолжаю работу со следующим изображением, он вылетает примерно через 5 пролистываний. Мне кажется, что изображения кэшируются и очищаются, когда занимаемое пространство становится слишком большим.
4. Мы использовали
photo_view
пакет. Смотрите эту все еще открытую проблему, в ней есть возможное исправление: github.com/bluefireteam/photo_view/issues/478