leaks: imageinfo, notifiers

This commit is contained in:
Thibault Deckers 2024-06-17 21:03:55 +02:00
parent 4116a55f8d
commit 4e811cc37c
8 changed files with 27 additions and 7 deletions

View file

@ -113,11 +113,13 @@ class _CollectionGridContent extends StatefulWidget {
class _CollectionGridContentState extends State<_CollectionGridContent> { class _CollectionGridContentState extends State<_CollectionGridContent> {
final ValueNotifier<AvesEntry?> _focusedItemNotifier = ValueNotifier(null); final ValueNotifier<AvesEntry?> _focusedItemNotifier = ValueNotifier(null);
final ValueNotifier<bool> _isScrollingNotifier = ValueNotifier(false); final ValueNotifier<bool> _isScrollingNotifier = ValueNotifier(false);
final ValueNotifier<AppMode> _selectingAppModeNotifier = ValueNotifier(AppMode.pickFilteredMediaInternal);
@override @override
void dispose() { void dispose() {
_focusedItemNotifier.dispose(); _focusedItemNotifier.dispose();
_isScrollingNotifier.dispose(); _isScrollingNotifier.dispose();
_selectingAppModeNotifier.dispose();
super.dispose(); super.dispose();
} }
@ -252,7 +254,7 @@ class _CollectionGridContentState extends State<_CollectionGridContent> {
if (selection.isSelecting) { if (selection.isSelecting) {
child = MultiProvider( child = MultiProvider(
providers: [ providers: [
ListenableProvider<ValueNotifier<AppMode>>.value(value: ValueNotifier(AppMode.pickFilteredMediaInternal)), ListenableProvider<ValueNotifier<AppMode>>.value(value: _selectingAppModeNotifier),
ChangeNotifierProvider<Selection<AvesEntry>>.value(value: selection), ChangeNotifierProvider<Selection<AvesEntry>>.value(value: selection),
], ],
child: child, child: child,

View file

@ -64,6 +64,7 @@ class _AlbumPickPage extends StatefulWidget {
class _AlbumPickPageState extends State<_AlbumPickPage> { class _AlbumPickPageState extends State<_AlbumPickPage> {
final ValueNotifier<double> _appBarHeightNotifier = ValueNotifier(0); final ValueNotifier<double> _appBarHeightNotifier = ValueNotifier(0);
final ValueNotifier<AppMode> _appModeNotifier = ValueNotifier(AppMode.pickFilterInternal);
CollectionSource get source => widget.source; CollectionSource get source => widget.source;
@ -93,13 +94,14 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
@override @override
void dispose() { void dispose() {
_appBarHeightNotifier.dispose(); _appBarHeightNotifier.dispose();
_appModeNotifier.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListenableProvider<ValueNotifier<AppMode>>.value( return ListenableProvider<ValueNotifier<AppMode>>.value(
value: ValueNotifier(AppMode.pickFilterInternal), value: _appModeNotifier,
child: Selector<Settings, (AlbumChipGroupFactor, ChipSortFactor)>( child: Selector<Settings, (AlbumChipGroupFactor, ChipSortFactor)>(
selector: (context, s) => (s.albumGroupFactor, s.albumSortFactor), selector: (context, s) => (s.albumGroupFactor, s.albumSortFactor),
builder: (context, s, child) { builder: (context, s, child) {

View file

@ -29,20 +29,23 @@ class ItemPickPage extends StatefulWidget {
} }
class _ItemPickPageState extends State<ItemPickPage> { class _ItemPickPageState extends State<ItemPickPage> {
final ValueNotifier<AppMode> _appModeNotifier = ValueNotifier(AppMode.initialization);
CollectionLens get collection => widget.collection; CollectionLens get collection => widget.collection;
@override @override
void dispose() { void dispose() {
collection.dispose(); collection.dispose();
_appModeNotifier.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final liveFilter = collection.filters.firstWhereOrNull((v) => v is QueryFilter && v.live) as QueryFilter?; final liveFilter = collection.filters.firstWhereOrNull((v) => v is QueryFilter && v.live) as QueryFilter?;
final mode = widget.canRemoveFilters ? AppMode.pickUnfilteredMediaInternal : AppMode.pickFilteredMediaInternal; _appModeNotifier.value = widget.canRemoveFilters ? AppMode.pickUnfilteredMediaInternal : AppMode.pickFilteredMediaInternal;
return ListenableProvider<ValueNotifier<AppMode>>.value( return ListenableProvider<ValueNotifier<AppMode>>.value(
value: ValueNotifier(mode), value: _appModeNotifier,
child: AvesScaffold( child: AvesScaffold(
body: SelectionProvider<AvesEntry>( body: SelectionProvider<AvesEntry>(
child: QueryProvider( child: QueryProvider(

View file

@ -53,8 +53,10 @@ class _ImageHistogramState extends State<ImageHistogram> {
void _registerWidget(ImageHistogram widget) { void _registerWidget(ImageHistogram widget) {
_imageStream = imageProvider.resolve(ImageConfiguration.empty); _imageStream = imageProvider.resolve(ImageConfiguration.empty);
_imageListener = ImageStreamListener((image, synchronousCall) { _imageListener = ImageStreamListener((image, synchronousCall) async {
_updateLevels(image); // implementer is responsible for disposing the provided `ImageInfo`
await _updateLevels(image);
image.dispose();
}); });
_imageStream?.addListener(_imageListener); _imageStream?.addListener(_imageListener);
} }

View file

@ -35,6 +35,7 @@ class SlideshowPage extends StatefulWidget {
} }
class _SlideshowPageState extends State<SlideshowPage> { class _SlideshowPageState extends State<SlideshowPage> {
final ValueNotifier<AppMode> _appModeNotifier = ValueNotifier(AppMode.slideshow);
late ViewerController _viewerController; late ViewerController _viewerController;
late CollectionLens _slideshowCollection; late CollectionLens _slideshowCollection;
AvesEntry? _initialEntry; AvesEntry? _initialEntry;
@ -51,6 +52,7 @@ class _SlideshowPageState extends State<SlideshowPage> {
@override @override
void dispose() { void dispose() {
_appModeNotifier.dispose();
_disposeViewerController(); _disposeViewerController();
super.dispose(); super.dispose();
} }
@ -59,7 +61,7 @@ class _SlideshowPageState extends State<SlideshowPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final initialEntry = _initialEntry; final initialEntry = _initialEntry;
return ListenableProvider<ValueNotifier<AppMode>>.value( return ListenableProvider<ValueNotifier<AppMode>>.value(
value: ValueNotifier(AppMode.slideshow), value: _appModeNotifier,
child: AvesScaffold( child: AvesScaffold(
body: initialEntry == null body: initialEntry == null
? EmptyContent( ? EmptyContent(

View file

@ -41,6 +41,7 @@ class _RasterImageViewState extends State<RasterImageView> {
ImageStream? _fullImageStream; ImageStream? _fullImageStream;
late ImageStreamListener _fullImageListener; late ImageStreamListener _fullImageListener;
final ValueNotifier<bool> _fullImageLoaded = ValueNotifier(false); final ValueNotifier<bool> _fullImageLoaded = ValueNotifier(false);
ImageInfo? _fullImageInfo;
AvesEntry get entry => widget.entry; AvesEntry get entry => widget.entry;
@ -101,10 +102,13 @@ class _RasterImageViewState extends State<RasterImageView> {
void _unregisterFullImage() { void _unregisterFullImage() {
_fullImageStream?.removeListener(_fullImageListener); _fullImageStream?.removeListener(_fullImageListener);
_fullImageStream = null; _fullImageStream = null;
_fullImageInfo?.dispose();
} }
void _onFullImageCompleted(ImageInfo image, bool synchronousCall) { void _onFullImageCompleted(ImageInfo image, bool synchronousCall) {
// implementer is responsible for disposing the provided `ImageInfo`
_unregisterFullImage(); _unregisterFullImage();
_fullImageInfo = image;
_fullImageLoaded.value = true; _fullImageLoaded.value = true;
FullImageLoadedNotification(entry, fullImageProvider).dispatch(context); FullImageLoadedNotification(entry, fullImageProvider).dispatch(context);
} }

View file

@ -37,6 +37,7 @@ class _VectorImageViewState extends State<VectorImageView> {
ImageStream? _fullImageStream; ImageStream? _fullImageStream;
late ImageStreamListener _fullImageListener; late ImageStreamListener _fullImageListener;
final ValueNotifier<bool> _fullImageLoaded = ValueNotifier(false); final ValueNotifier<bool> _fullImageLoaded = ValueNotifier(false);
ImageInfo? _fullImageInfo;
AvesEntry get entry => widget.entry; AvesEntry get entry => widget.entry;
@ -91,10 +92,13 @@ class _VectorImageViewState extends State<VectorImageView> {
void _unregisterFullImage() { void _unregisterFullImage() {
_fullImageStream?.removeListener(_fullImageListener); _fullImageStream?.removeListener(_fullImageListener);
_fullImageStream = null; _fullImageStream = null;
_fullImageInfo?.dispose();
} }
void _onFullImageCompleted(ImageInfo image, bool synchronousCall) { void _onFullImageCompleted(ImageInfo image, bool synchronousCall) {
// implementer is responsible for disposing the provided `ImageInfo`
_unregisterFullImage(); _unregisterFullImage();
_fullImageInfo = image;
_fullImageLoaded.value = true; _fullImageLoaded.value = true;
} }

View file

@ -47,6 +47,7 @@ abstract class AvesVideoController with ABRepeatMixin {
if (kFlutterMemoryAllocationsEnabled) { if (kFlutterMemoryAllocationsEnabled) {
FlutterMemoryAllocations.instance.dispatchObjectDisposed(object: this); FlutterMemoryAllocations.instance.dispatchObjectDisposed(object: this);
} }
abRepeatNotifier.dispose();
_entry.visualChangeNotifier.removeListener(onVisualChanged); _entry.visualChangeNotifier.removeListener(onVisualChanged);
await _savePlaybackState(); await _savePlaybackState();
} }