viewer: improved video controller disposing
This commit is contained in:
parent
1fd3d77bf9
commit
969187444b
2 changed files with 19 additions and 12 deletions
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:aves/model/entry/entry.dart';
|
||||
import 'package:aves/model/entry/extensions/props.dart';
|
||||
|
@ -15,7 +16,7 @@ import 'package:leak_tracker/leak_tracker.dart';
|
|||
class VideoConductor {
|
||||
final CollectionLens? _collection;
|
||||
final List<AvesVideoController> _controllers = [];
|
||||
final List<StreamSubscription> _subscriptions = [];
|
||||
final Map<AvesVideoController, StreamSubscription> _subscriptions = {};
|
||||
final PlaybackStateHandler _playbackStateHandler = DatabasePlaybackStateHandler();
|
||||
|
||||
final ValueNotifier<AvesVideoController?> playingVideoControllerNotifier = ValueNotifier(null);
|
||||
|
@ -36,9 +37,6 @@ class VideoConductor {
|
|||
if (kFlutterMemoryAllocationsEnabled) {
|
||||
LeakTracking.dispatchObjectDisposed(object: this);
|
||||
}
|
||||
_subscriptions
|
||||
..forEach((sub) => sub.cancel())
|
||||
..clear();
|
||||
await _disposeAll();
|
||||
playingVideoControllerNotifier.dispose();
|
||||
_controllers.clear();
|
||||
|
@ -47,22 +45,24 @@ class VideoConductor {
|
|||
}
|
||||
}
|
||||
|
||||
AvesVideoController getOrCreateController(AvesEntry entry, {int? maxControllerCount}) {
|
||||
Future<AvesVideoController> getOrCreateController(AvesEntry entry, {int? maxControllerCount}) async {
|
||||
var controller = getController(entry);
|
||||
if (controller != null) {
|
||||
_controllers.remove(controller);
|
||||
} else {
|
||||
maxControllerCount = max(_defaultMaxControllerCount, maxControllerCount ?? 0);
|
||||
while (_controllers.length >= maxControllerCount) {
|
||||
await _disposeController(_controllers.removeLast());
|
||||
}
|
||||
await deviceService.requestGarbageCollection();
|
||||
controller = videoControllerFactory.buildController(
|
||||
entry,
|
||||
playbackStateHandler: _playbackStateHandler,
|
||||
settings: settings,
|
||||
);
|
||||
_subscriptions.add(controller.statusStream.listen((event) => _onControllerStatusChanged(entry, controller!, event)));
|
||||
_subscriptions[controller] = controller.statusStream.listen((event) => _onControllerStatusChanged(entry, controller!, event));
|
||||
}
|
||||
_controllers.insert(0, controller);
|
||||
while (_controllers.length > (maxControllerCount ?? _defaultMaxControllerCount)) {
|
||||
_controllers.removeLast().dispose();
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,14 @@ class VideoConductor {
|
|||
|
||||
Future<void> _applyToAll(FutureOr Function(AvesVideoController controller) action) => Future.forEach<AvesVideoController>(_controllers, action);
|
||||
|
||||
Future<void> _disposeAll() => _applyToAll((controller) => controller.dispose());
|
||||
Future<void> _disposeAll() => _applyToAll(_disposeController);
|
||||
|
||||
Future<void> pauseAll() => _applyToAll((controller) => controller.pause());
|
||||
|
||||
Future<void> muteAll(bool muted) => _applyToAll((controller) => controller.mute(muted));
|
||||
|
||||
Future<void> _disposeController(AvesVideoController controller) async {
|
||||
await _subscriptions.remove(controller)?.cancel();
|
||||
await controller.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
|||
}
|
||||
|
||||
Future<void> _initVideoController(AvesEntry entry) async {
|
||||
final controller = context.read<VideoConductor>().getOrCreateController(entry);
|
||||
final controller = await context.read<VideoConductor>().getOrCreateController(entry);
|
||||
setState(() {});
|
||||
|
||||
if (videoAutoPlayEnabled || entry.isAnimated) {
|
||||
|
@ -157,7 +157,9 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
|||
if (videoPageEntries.isNotEmpty) {
|
||||
// init video controllers for all pages that could need it
|
||||
final videoConductor = context.read<VideoConductor>();
|
||||
videoPageEntries.forEach((entry) => videoConductor.getOrCreateController(entry, maxControllerCount: videoPageEntries.length));
|
||||
await Future.forEach(videoPageEntries, (entry) async {
|
||||
await videoConductor.getOrCreateController(entry, maxControllerCount: videoPageEntries.length);
|
||||
});
|
||||
|
||||
// auto play/pause when changing page
|
||||
Future<void> _onPageChanged() async {
|
||||
|
|
Loading…
Reference in a new issue