From 506190f882d18789c0a276bd004e48da37299b33 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 21 Oct 2023 00:31:06 +0300 Subject: [PATCH] memory leak tracking & fixes --- lib/widgets/collection/app_bar.dart | 1 - lib/widgets/collection/collection_grid.dart | 2 +- .../action_controls/togglers/favourite.dart | 18 +++++++++--------- .../common/action_mixins/entry_storage.dart | 13 ++++++++++--- lib/widgets/common/identity/aves_app_bar.dart | 1 + lib/widgets/common/thumbnail/overlay.dart | 6 ++++++ lib/widgets/common/thumbnail/scroller.dart | 3 ++- lib/widgets/dialogs/add_shortcut_dialog.dart | 1 + .../dialogs/aves_confirmation_dialog.dart | 14 ++++++++++---- lib/widgets/dialogs/convert_entry_dialog.dart | 2 ++ lib/widgets/dialogs/duration_dialog.dart | 7 +++++++ .../entry_editors/edit_date_dialog.dart | 3 +++ .../entry_editors/edit_location_dialog.dart | 1 + .../entry_editors/remove_metadata_dialog.dart | 6 ++++++ .../entry_editors/rename_entry_dialog.dart | 1 + .../dialogs/pick_dialogs/album_pick_page.dart | 6 ++++++ .../pick_dialogs/location_pick_page.dart | 4 +++- lib/widgets/dialogs/tile_view_dialog.dart | 6 ++++++ lib/widgets/filter_grids/common/app_bar.dart | 1 - .../filter_grids/common/filter_nav_page.dart | 6 ++++++ lib/widgets/filter_grids/common/overlay.dart | 6 ++++++ lib/widgets/map/map_page.dart | 14 ++++++++++---- .../common/quick_actions/editor_page.dart | 6 ++++++ lib/widgets/stats/stats_page.dart | 6 ++++++ lib/widgets/viewer/controls/controller.dart | 2 +- lib/widgets/viewer/info/metadata/xmp_card.dart | 6 ++++++ lib/widgets/viewer/panorama_page.dart | 3 ++- lib/widgets/viewer/visual/raster.dart | 1 + lib/widgets/viewer/visual/vector.dart | 1 + lib/widgets/wallpaper_page.dart | 6 +++--- plugins/aves_model/lib/src/settings/keys.dart | 2 +- plugins/aves_video/lib/src/controller.dart | 11 +++++++---- plugins/aves_video_ijk/lib/src/controller.dart | 7 +++++++ plugins/aves_video_mpv/lib/src/controller.dart | 11 ++++++++--- 34 files changed, 146 insertions(+), 38 deletions(-) diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index 542cdede8..5ca14047a 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -123,7 +123,6 @@ class _CollectionAppBarState extends State with SingleTickerPr _unregisterWidget(widget); _queryBarFocusNode.dispose(); _queryFocusRequestNotifier.removeListener(_onQueryFocusRequest); - _isSelectingNotifier.removeListener(_onActivityChanged); _isSelectingNotifier.dispose(); _browseToSelectAnimation.dispose(); _subscriptions diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 974eba8bc..01b401e71 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -302,7 +302,7 @@ class _CollectionSectionedContentState extends State<_CollectionSectionedContent @override void dispose() { - _appBarHeightNotifier.removeListener(_onAppBarHeightChanged); + _appBarHeightNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/common/action_controls/togglers/favourite.dart b/lib/widgets/common/action_controls/togglers/favourite.dart index 4589b528e..31b0bbd79 100644 --- a/lib/widgets/common/action_controls/togglers/favourite.dart +++ b/lib/widgets/common/action_controls/togglers/favourite.dart @@ -29,7 +29,7 @@ class FavouriteToggler extends StatefulWidget { } class _FavouriteTogglerState extends State { - final ValueNotifier isFavouriteNotifier = ValueNotifier(false); + final ValueNotifier _isFavouriteNotifier = ValueNotifier(false); Set get entries => widget.entries; @@ -53,14 +53,14 @@ class _FavouriteTogglerState extends State { @override void dispose() { favourites.removeListener(_onChanged); - isFavouriteNotifier.dispose(); + _isFavouriteNotifier.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ValueListenableBuilder( - valueListenable: isFavouriteNotifier, + valueListenable: _isFavouriteNotifier, builder: (context, isFavourite, child) { if (widget.isMenuItem) { return isFavourite @@ -88,7 +88,7 @@ class _FavouriteTogglerState extends State { favouriteSweeperIcon, color: context.select((v) => v.favourite), ), - toggledNotifier: isFavouriteNotifier, + toggledNotifier: _isFavouriteNotifier, ), ], ); @@ -97,7 +97,7 @@ class _FavouriteTogglerState extends State { } void _onChanged() { - isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite); + _isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite); } } @@ -116,7 +116,7 @@ class FavouriteTogglerCaption extends StatefulWidget { } class _FavouriteTogglerCaptionState extends State { - final ValueNotifier isFavouriteNotifier = ValueNotifier(false); + final ValueNotifier _isFavouriteNotifier = ValueNotifier(false); Set get entries => widget.entries; @@ -136,14 +136,14 @@ class _FavouriteTogglerCaptionState extends State { @override void dispose() { favourites.removeListener(_onChanged); - isFavouriteNotifier.dispose(); + _isFavouriteNotifier.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ValueListenableBuilder( - valueListenable: isFavouriteNotifier, + valueListenable: _isFavouriteNotifier, builder: (context, isFavourite, child) { return CaptionedButtonText( text: isFavourite ? context.l10n.entryActionRemoveFavourite : context.l10n.entryActionAddFavourite, @@ -154,6 +154,6 @@ class _FavouriteTogglerCaptionState extends State { } void _onChanged() { - isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite); + _isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite); } } diff --git a/lib/widgets/common/action_mixins/entry_storage.dart b/lib/widgets/common/action_mixins/entry_storage.dart index 3cb84cb70..be9f0e111 100644 --- a/lib/widgets/common/action_mixins/entry_storage.dart +++ b/lib/widgets/common/action_mixins/entry_storage.dart @@ -391,12 +391,15 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { return dateMillis == null || dateMillis == 0; }).toSet(); if (undatedItems.isNotEmpty) { - if (!await showSkippableConfirmationDialog( + final confirmationDialogDelegate = MoveUndatedConfirmationDialogDelegate(); + final confirmed = await showSkippableConfirmationDialog( context: context, type: ConfirmationDialog.moveUndatedItems, - delegate: MoveUndatedConfirmationDialogDelegate(), + delegate: confirmationDialogDelegate, confirmationButtonLabel: context.l10n.continueButtonLabel, - )) return false; + ); + confirmationDialogDelegate.dispose(); + if (!confirmed) return false; if (settings.setMetadataDateBeforeFileOp) { final entriesToDate = undatedItems.where((entry) => entry.canEditDate).toSet(); @@ -461,6 +464,10 @@ class MoveUndatedConfirmationDialogDelegate extends ConfirmationDialogDelegate { _setMetadataDate.value = settings.setMetadataDateBeforeFileOp; } + void dispose() { + _setMetadataDate.dispose(); + } + @override List build(BuildContext context) => [ Padding( diff --git a/lib/widgets/common/identity/aves_app_bar.dart b/lib/widgets/common/identity/aves_app_bar.dart index 590be02f1..0629d5c24 100644 --- a/lib/widgets/common/identity/aves_app_bar.dart +++ b/lib/widgets/common/identity/aves_app_bar.dart @@ -190,6 +190,7 @@ class _AvesFloatingBarState extends State with RouteAware { @override void dispose() { AvesApp.pageRouteObserver.unsubscribe(this); + _isBlurAllowedNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/common/thumbnail/overlay.dart b/lib/widgets/common/thumbnail/overlay.dart index e1e2dd518..4c2732778 100644 --- a/lib/widgets/common/thumbnail/overlay.dart +++ b/lib/widgets/common/thumbnail/overlay.dart @@ -53,6 +53,12 @@ class _ThumbnailHighlightOverlayState extends State { static const startAngle = pi * -3 / 4; + @override + void dispose() { + _highlightedNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final highlightInfo = context.watch(); diff --git a/lib/widgets/common/thumbnail/scroller.dart b/lib/widgets/common/thumbnail/scroller.dart index 40dd73e6a..c0adf63d1 100644 --- a/lib/widgets/common/thumbnail/scroller.dart +++ b/lib/widgets/common/thumbnail/scroller.dart @@ -36,7 +36,7 @@ class ThumbnailScroller extends StatefulWidget { } class _ThumbnailScrollerState extends State { - final _cancellableNotifier = ValueNotifier(true); + final ValueNotifier _cancellableNotifier = ValueNotifier(true); late ScrollController _scrollController; bool _isAnimating = false, _isScrolling = false; @@ -71,6 +71,7 @@ class _ThumbnailScrollerState extends State { @override void dispose() { _unregisterWidget(widget); + _cancellableNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/add_shortcut_dialog.dart b/lib/widgets/dialogs/add_shortcut_dialog.dart index 308a2d1a1..88af929c3 100644 --- a/lib/widgets/dialogs/add_shortcut_dialog.dart +++ b/lib/widgets/dialogs/add_shortcut_dialog.dart @@ -50,6 +50,7 @@ class _AddShortcutDialogState extends State { @override void dispose() { _nameController.dispose(); + _isValidNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/aves_confirmation_dialog.dart b/lib/widgets/dialogs/aves_confirmation_dialog.dart index dd9f4b312..6e1a61a13 100644 --- a/lib/widgets/dialogs/aves_confirmation_dialog.dart +++ b/lib/widgets/dialogs/aves_confirmation_dialog.dart @@ -119,7 +119,13 @@ class _SkippableConfirmationDialog extends StatefulWidget { } class _SkippableConfirmationDialogState extends State<_SkippableConfirmationDialog> { - final ValueNotifier _skip = ValueNotifier(false); + final ValueNotifier _skipNotifier = ValueNotifier(false); + + @override + void dispose() { + _skipNotifier.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -127,10 +133,10 @@ class _SkippableConfirmationDialogState extends State<_SkippableConfirmationDial scrollableContent: [ ...widget.delegate.build(context), ValueListenableBuilder( - valueListenable: _skip, + valueListenable: _skipNotifier, builder: (context, flag, child) => SwitchListTile( value: flag, - onChanged: (v) => _skip.value = v, + onChanged: (v) => _skipNotifier.value = v, title: Text(context.l10n.doNotAskAgain), ), ), @@ -139,7 +145,7 @@ class _SkippableConfirmationDialogState extends State<_SkippableConfirmationDial const CancelButton(), TextButton( onPressed: () { - if (_skip.value) { + if (_skipNotifier.value) { _skipConfirmation(widget.type); } Navigator.maybeOf(context)?.pop(true); diff --git a/lib/widgets/dialogs/convert_entry_dialog.dart b/lib/widgets/dialogs/convert_entry_dialog.dart index fe9bae4a0..1721dda61 100644 --- a/lib/widgets/dialogs/convert_entry_dialog.dart +++ b/lib/widgets/dialogs/convert_entry_dialog.dart @@ -88,6 +88,8 @@ class _ConvertEntryDialogState extends State { void dispose() { _widthController.dispose(); _heightController.dispose(); + _isValidNotifier.dispose(); + _mimeTypeNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/duration_dialog.dart b/lib/widgets/dialogs/duration_dialog.dart index b6a6b920b..22190f831 100644 --- a/lib/widgets/dialogs/duration_dialog.dart +++ b/lib/widgets/dialogs/duration_dialog.dart @@ -28,6 +28,13 @@ class _DurationDialogState extends State { _seconds = ValueNotifier(seconds % secondsInMinute); } + @override + void dispose() { + _minutes.dispose(); + _seconds.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return MediaQueryDataProvider( diff --git a/lib/widgets/dialogs/entry_editors/edit_date_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_date_dialog.dart index bd40664d6..fd4b72d3f 100644 --- a/lib/widgets/dialogs/entry_editors/edit_date_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_date_dialog.dart @@ -60,6 +60,9 @@ class _EditEntryDateDialogState extends State { @override void dispose() { _isValidNotifier.dispose(); + _shiftHour.dispose(); + _shiftMinute.dispose(); + _shiftSign.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/entry_editors/edit_location_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_location_dialog.dart index 1cad7d7e4..2d6196654 100644 --- a/lib/widgets/dialogs/entry_editors/edit_location_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_location_dialog.dart @@ -82,6 +82,7 @@ class _EditEntryLocationDialogState extends State { void dispose() { _latitudeController.dispose(); _longitudeController.dispose(); + _isValidNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/entry_editors/remove_metadata_dialog.dart b/lib/widgets/dialogs/entry_editors/remove_metadata_dialog.dart index 18bff131c..a890abc78 100644 --- a/lib/widgets/dialogs/entry_editors/remove_metadata_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/remove_metadata_dialog.dart @@ -45,6 +45,12 @@ class _RemoveEntryMetadataDialogState extends State { _validate(); } + @override + void dispose() { + _isValidNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final l10n = context.l10n; diff --git a/lib/widgets/dialogs/entry_editors/rename_entry_dialog.dart b/lib/widgets/dialogs/entry_editors/rename_entry_dialog.dart index c524323bb..05d4f89f1 100644 --- a/lib/widgets/dialogs/entry_editors/rename_entry_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/rename_entry_dialog.dart @@ -37,6 +37,7 @@ class _RenameEntryDialogState extends State { @override void dispose() { _nameController.dispose(); + _isValidNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart index c2055cb6d..259c40606 100644 --- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart @@ -89,6 +89,12 @@ class _AlbumPickPageState extends State<_AlbumPickPage> { ChipSetAction.createVault, ]; + @override + void dispose() { + _appBarHeightNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return ListenableProvider>.value( diff --git a/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart index 452f3e9d2..6ceb180c1 100644 --- a/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/location_pick_page.dart @@ -96,8 +96,10 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin _subscriptions ..forEach((sub) => sub.cancel()) ..clear(); - _dotLocationNotifier.removeListener(_updateLocationInfo); _mapController.dispose(); + _isPageAnimatingNotifier.dispose(); + _dotLocationNotifier.dispose(); + _infoLocationNotifier.dispose(); super.dispose(); } diff --git a/lib/widgets/dialogs/tile_view_dialog.dart b/lib/widgets/dialogs/tile_view_dialog.dart index 2c0af6253..2cf1de077 100644 --- a/lib/widgets/dialogs/tile_view_dialog.dart +++ b/lib/widgets/dialogs/tile_view_dialog.dart @@ -73,6 +73,12 @@ class _TileViewDialogState extends State> with _columnMax = columnRange.$2; } + @override + void dispose() { + _columnCountNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final l10n = context.l10n; diff --git a/lib/widgets/filter_grids/common/app_bar.dart b/lib/widgets/filter_grids/common/app_bar.dart index d68cc0878..1c837456d 100644 --- a/lib/widgets/filter_grids/common/app_bar.dart +++ b/lib/widgets/filter_grids/common/app_bar.dart @@ -111,7 +111,6 @@ class _FilterGridAppBarState> extends State> { final ValueNotifier _appBarHeightNotifier = ValueNotifier(0); + @override + void dispose() { + _appBarHeightNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return SelectionProvider>( diff --git a/lib/widgets/filter_grids/common/overlay.dart b/lib/widgets/filter_grids/common/overlay.dart index 1e479a9d8..2b520944b 100644 --- a/lib/widgets/filter_grids/common/overlay.dart +++ b/lib/widgets/filter_grids/common/overlay.dart @@ -27,6 +27,12 @@ class _ChipHighlightOverlayState extends State { CollectionFilter get filter => widget.filter; + @override + void dispose() { + _highlightedNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final highlightInfo = context.watch(); diff --git a/lib/widgets/map/map_page.dart b/lib/widgets/map/map_page.dart index 8367eeb44..372db19dd 100644 --- a/lib/widgets/map/map_page.dart +++ b/lib/widgets/map/map_page.dart @@ -159,12 +159,18 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin _subscriptions ..forEach((sub) => sub.cancel()) ..clear(); - _dotEntryNotifier.value?.metadataChangeNotifier.removeListener(_onMarkerEntryMetadataChanged); - _overlayAnimationController.dispose(); - _overlayVisible.removeListener(_onOverlayVisibleChanged); _mapController.dispose(); + _isPageAnimatingNotifier.dispose(); _selectedIndexNotifier.dispose(); - regionCollection?.dispose(); + _regionCollectionNotifier.value?.dispose(); + _regionCollectionNotifier.dispose(); + _dotLocationNotifier.dispose(); + _dotEntryNotifier.value?.metadataChangeNotifier.removeListener(_onMarkerEntryMetadataChanged); + _dotEntryNotifier.dispose(); + _overlayOpacityNotifier.dispose(); + _overlayVisible.dispose(); + _overlayAnimationController.dispose(); + // provided collection should be a new instance specifically created // for the `MapPage` widget, so it can be safely disposed here widget.collection.dispose(); diff --git a/lib/widgets/settings/common/quick_actions/editor_page.dart b/lib/widgets/settings/common/quick_actions/editor_page.dart index 8b8a8758a..2f50fb405 100644 --- a/lib/widgets/settings/common/quick_actions/editor_page.dart +++ b/lib/widgets/settings/common/quick_actions/editor_page.dart @@ -104,7 +104,13 @@ class _QuickActionEditorBodyState extends State with FeedbackMixin, VaultAwareMix }); } + @override + void dispose() { + _isPageAnimatingNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final useTvLayout = settings.useTvLayout; diff --git a/lib/widgets/viewer/controls/controller.dart b/lib/widgets/viewer/controls/controller.dart index fe5bbaf6c..e92ad27ab 100644 --- a/lib/widgets/viewer/controls/controller.dart +++ b/lib/widgets/viewer/controls/controller.dart @@ -65,7 +65,7 @@ class ViewerController { if (kFlutterMemoryAllocationsEnabled) { MemoryAllocations.instance.dispatchObjectDisposed(object: this); } - _autopilotNotifier.removeListener(_onAutopilotChanged); + _autopilotNotifier.dispose(); _clearAutopilotAnimations(); _stopPlayTimer(); _streamController.close(); diff --git a/lib/widgets/viewer/info/metadata/xmp_card.dart b/lib/widgets/viewer/info/metadata/xmp_card.dart index ac359fa52..49ec41cf1 100644 --- a/lib/widgets/viewer/info/metadata/xmp_card.dart +++ b/lib/widgets/viewer/info/metadata/xmp_card.dart @@ -61,6 +61,12 @@ class _XmpCardState extends State { } } + @override + void dispose() { + _indexNotifier.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final _isIndexed = isIndexed; diff --git a/lib/widgets/viewer/panorama_page.dart b/lib/widgets/viewer/panorama_page.dart index 464dc5dc8..feaebfe1f 100644 --- a/lib/widgets/viewer/panorama_page.dart +++ b/lib/widgets/viewer/panorama_page.dart @@ -50,7 +50,8 @@ class _PanoramaPageState extends State { @override void dispose() { - _overlayVisible.removeListener(_onOverlayVisibleChanged); + _overlayVisible.dispose(); + _sensorControl.dispose(); super.dispose(); } diff --git a/lib/widgets/viewer/visual/raster.dart b/lib/widgets/viewer/visual/raster.dart index c90f8744b..7e38eed88 100644 --- a/lib/widgets/viewer/visual/raster.dart +++ b/lib/widgets/viewer/visual/raster.dart @@ -88,6 +88,7 @@ class _RasterImageViewState extends State { @override void dispose() { + _fullImageLoaded.dispose(); _unregisterFullImage(); super.dispose(); } diff --git a/lib/widgets/viewer/visual/vector.dart b/lib/widgets/viewer/visual/vector.dart index fbc535646..eae983d37 100644 --- a/lib/widgets/viewer/visual/vector.dart +++ b/lib/widgets/viewer/visual/vector.dart @@ -78,6 +78,7 @@ class _VectorImageViewState extends State { @override void dispose() { + _fullImageLoaded.dispose(); _unregisterFullImage(); super.dispose(); } diff --git a/lib/widgets/wallpaper_page.dart b/lib/widgets/wallpaper_page.dart index 5d9311ac7..ad67533fa 100644 --- a/lib/widgets/wallpaper_page.dart +++ b/lib/widgets/wallpaper_page.dart @@ -119,10 +119,10 @@ class _EntryEditorState extends State with EntryViewControllerMixin @override void dispose() { cleanEntryControllers(entry); - _viewerController.dispose(); - _videoActionDelegate.dispose(); + _overlayVisible.dispose(); _overlayAnimationController.dispose(); - _overlayVisible.removeListener(_onOverlayVisibleChanged); + _videoActionDelegate.dispose(); + _viewerController.dispose(); super.dispose(); } diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart index 36f03e422..77dd5b85e 100644 --- a/plugins/aves_model/lib/src/settings/keys.dart +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -183,4 +183,4 @@ class SettingKeys { // cf Android `Settings.Global.TRANSITION_ANIMATION_SCALE` static const platformTransitionAnimationScaleKey = 'transition_animation_scale'; -} \ No newline at end of file +} diff --git a/plugins/aves_video/lib/src/controller.dart b/plugins/aves_video/lib/src/controller.dart index ae1caf801..9894fed83 100644 --- a/plugins/aves_video/lib/src/controller.dart +++ b/plugins/aves_video/lib/src/controller.dart @@ -9,16 +9,17 @@ abstract class AvesVideoControllerFactory { void init(); AvesVideoController buildController( - AvesEntryBase entry, { - required PlaybackStateHandler playbackStateHandler, - required VideoSettings settings, - }); + AvesEntryBase entry, { + required PlaybackStateHandler playbackStateHandler, + required VideoSettings settings, + }); } abstract class AvesVideoController { final AvesEntryBase _entry; final PlaybackStateHandler playbackStateHandler; final VideoSettings settings; + bool _disposed = false; AvesEntryBase get entry => _entry; @@ -41,6 +42,8 @@ abstract class AvesVideoController { @mustCallSuper Future dispose() async { + assert(!_disposed); + _disposed = true; if (kFlutterMemoryAllocationsEnabled) { MemoryAllocations.instance.dispatchObjectDisposed(object: this); } diff --git a/plugins/aves_video_ijk/lib/src/controller.dart b/plugins/aves_video_ijk/lib/src/controller.dart index b13417263..0b594406d 100644 --- a/plugins/aves_video_ijk/lib/src/controller.dart +++ b/plugins/aves_video_ijk/lib/src/controller.dart @@ -80,12 +80,19 @@ class IjkVideoController extends AvesVideoController { @override Future dispose() async { await super.dispose(); + _initialPlayTimer?.cancel(); _stopListening(); await _valueStreamController.close(); await _timedTextStreamController.close(); await _instance.release(); + _completedNotifier.dispose(); + canCaptureFrameNotifier.dispose(); + canMuteNotifier.dispose(); + canSetSpeedNotifier.dispose(); + canSelectStreamNotifier.dispose(); + sarNotifier.dispose(); } void _startListening() { diff --git a/plugins/aves_video_mpv/lib/src/controller.dart b/plugins/aves_video_mpv/lib/src/controller.dart index 5703c8fef..5b36db0ca 100644 --- a/plugins/aves_video_mpv/lib/src/controller.dart +++ b/plugins/aves_video_mpv/lib/src/controller.dart @@ -12,7 +12,7 @@ import 'package:media_kit_video/media_kit_video.dart'; class MpvVideoController extends AvesVideoController { late Player _instance; late VideoStatus _status; - bool _disposed = false, _firstFrameRendered = false; + bool _firstFrameRendered = false; final ValueNotifier _controllerNotifier = ValueNotifier(null); final List _subscriptions = []; final StreamController _statusStreamController = StreamController.broadcast(); @@ -63,16 +63,21 @@ class MpvVideoController extends AvesVideoController { @override Future dispose() async { - assert(!_disposed); - _disposed = true; await super.dispose(); + _stopListening(); _stopStreamFetchTimer(); await _statusStreamController.close(); await _timedTextStreamController.close(); await _instance.dispose(); _controllerNotifier.dispose(); + _completedNotifier.dispose(); + canCaptureFrameNotifier.dispose(); + canMuteNotifier.dispose(); + canSetSpeedNotifier.dispose(); + canSelectStreamNotifier.dispose(); + sarNotifier.dispose(); } void _startListening() {