From 72a6af5040a90d8d3075cfc13fa201df33076dc8 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 21 Dec 2023 18:33:36 +0100 Subject: [PATCH] memory leak fixes --- lib/model/multipage.dart | 19 ++++++++++++++++++- .../common/action_mixins/entry_storage.dart | 4 ++++ lib/widgets/viewer/multipage/controller.dart | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/model/multipage.dart b/lib/model/multipage.dart index 278a62e6a..286dda44d 100644 --- a/lib/model/multipage.dart +++ b/lib/model/multipage.dart @@ -9,6 +9,7 @@ class MultiPageInfo { final AvesEntry mainEntry; final List _pages; final Map _pageEntries = {}; + final Set _transientEntries = {}; int get pageCount => _pages.length; @@ -16,6 +17,13 @@ class MultiPageInfo { required this.mainEntry, required List pages, }) : _pages = pages { + if (kFlutterMemoryAllocationsEnabled) { + MemoryAllocations.instance.dispatchObjectCreated( + library: 'aves', + className: '$MultiPageInfo', + object: this, + ); + } if (_pages.isNotEmpty) { _pages.sort(); // make sure there is a page marked as default @@ -34,6 +42,13 @@ class MultiPageInfo { } } + void dispose() { + if (kFlutterMemoryAllocationsEnabled) { + MemoryAllocations.instance.dispatchObjectDisposed(object: this); + } + _transientEntries.forEach((entry) => entry.dispose()); + } + factory MultiPageInfo.fromPageMaps(AvesEntry mainEntry, List pageMaps) { return MultiPageInfo( mainEntry: mainEntry, @@ -91,7 +106,7 @@ class MultiPageInfo { // dynamically extracted video is not in the trash like the original motion photo final trashed = (mainEntry.isMotionPhoto && pageInfo.isVideo) ? false : mainEntry.trashed; - return AvesEntry( + final pageEntry = AvesEntry( id: mainEntry.id, uri: pageInfo.uri ?? mainEntry.uri, path: mainEntry.path, @@ -117,6 +132,8 @@ class MultiPageInfo { ) ..addressDetails = mainEntry.addressDetails?.copyWith() ..trashDetails = trashed ? mainEntry.trashDetails : null; + _transientEntries.add(pageEntry); + return pageEntry; } @override diff --git a/lib/widgets/common/action_mixins/entry_storage.dart b/lib/widgets/common/action_mixins/entry_storage.dart index be9f0e111..76eb30d8a 100644 --- a/lib/widgets/common/action_mixins/entry_storage.dart +++ b/lib/widgets/common/action_mixins/entry_storage.dart @@ -9,6 +9,7 @@ import 'package:aves/model/filters/album.dart'; import 'package:aves/model/filters/trash.dart'; import 'package:aves/model/highlight.dart'; import 'package:aves/model/metadata/date_modifier.dart'; +import 'package:aves/model/multipage.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; @@ -49,11 +50,13 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { if (!await checkFreeSpaceForMove(context, targetEntries, destinationAlbum, MoveType.export)) return; + final transientMultiPageInfo = {}; final selection = {}; await Future.forEach(targetEntries, (targetEntry) async { if (targetEntry.isMultiPage) { final multiPageInfo = await targetEntry.getMultiPageInfo(); if (multiPageInfo != null) { + transientMultiPageInfo.add(multiPageInfo); if (targetEntry.isMotionPhoto) { await multiPageInfo.extractMotionPhotoVideo(); } @@ -130,6 +133,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { } }, ); + transientMultiPageInfo.forEach((v) => v.dispose()); } Future doQuickMove( diff --git a/lib/widgets/viewer/multipage/controller.dart b/lib/widgets/viewer/multipage/controller.dart index 429fb582d..1dfa7abcf 100644 --- a/lib/widgets/viewer/multipage/controller.dart +++ b/lib/widgets/viewer/multipage/controller.dart @@ -50,6 +50,7 @@ class MultiPageController { if (kFlutterMemoryAllocationsEnabled) { MemoryAllocations.instance.dispatchObjectDisposed(object: this); } + _info?.dispose(); _disposed = true; pageNotifier.dispose(); }