Line data Source code
1 : // ignore_for_file: avoid_dynamic_calls 2 : 3 : import 'package:flutter/widgets.dart'; 4 : 5 : import '../../meedu.dart'; 6 : import 'router/contextless_navigator.dart'; 7 : 8 : /// this class is used to listen the changed in the stack route 9 : class MeeduNavigatorObserver extends NavigatorObserver { 10 : /// return a name for a route 11 5 : String _getRouteName(PageRoute route) { 12 10 : return '${route.hashCode}'; 13 : } 14 : 15 : /// check if the popped routes has notifier attached to it and dispose 16 : /// the notifiers and delete its from the ProviderScope 17 5 : Future<void> _checkAutoDispose(Route? route) async { 18 5 : if (route is PageRoute) { 19 5 : final routeName = _getRouteName(route); 20 : 21 : /// if we have notifiers into the ProviderScope 22 5 : if (ProviderScope.initialized && 23 9 : ProviderScope.instance.containers.isNotEmpty) { 24 : /// get all notifiers attached to the current route 25 8 : final containers = ProviderScope.instance.containers.values.where( 26 6 : (e) => e.routeName == routeName, 27 : ); 28 : 29 2 : final keysToRemove = <int>[]; // save the notifier's keys to be disposed 30 : 31 : // if the popped route has notifiers 32 2 : if (containers.isNotEmpty) { 33 4 : for (final container in containers) { 34 : // if the auto dispose is enabled 35 2 : if (container.autoDispose) { 36 : // save the key to be used later 37 4 : keysToRemove.add(container.providerHashCode); 38 4 : container.reference.dispose(); // dispose the current notifier 39 : } 40 : } 41 : 42 : // remove the notifiers for the ProviderScope 43 2 : if (keysToRemove.isNotEmpty) { 44 6 : ProviderScope.instance.containers.removeWhere( 45 4 : (key, value) => keysToRemove.contains(key), 46 : ); 47 : } 48 : } 49 : } 50 : 51 : /// get all dependencies injected using put or lazyPut 52 16 : Get.dependencies.removeWhere((key, value) { 53 3 : final remove = value.creatorName == routeName && value.autoRemove; 54 1 : final dependency = value.dependency; 55 : final dynamicValue = value as dynamic; 56 1 : if (remove && dynamicValue.onRemove != null) { 57 1 : dynamicValue.onRemove(dependency); 58 : } 59 : return remove; 60 : }); 61 : } 62 : } 63 : 64 : /// set the current route name 65 5 : void _setCurrentRoute( 66 : Route? route, { 67 : bool checkAutoDispose = false, 68 : }) { 69 10 : if (route is PageRoute && route.isCurrent) { 70 5 : BaseProvider.creatorName = _getRouteName(route); 71 15 : ContextlessNavigator.i.setRouteSettings(route.settings); 72 : if (checkAutoDispose) { 73 : // wait to the popped animation transisiton 74 20 : route.completed.then((_) => _checkAutoDispose(route)); 75 : } 76 : } 77 : } 78 : 79 2 : @override 80 : void didRemove(Route route, Route? previousRoute) { 81 2 : super.didRemove(route, previousRoute); 82 2 : _setCurrentRoute(previousRoute); 83 : } 84 : 85 4 : @override 86 : void didPop(Route route, Route? previousRoute) { 87 4 : super.didPop(route, previousRoute); 88 4 : _setCurrentRoute(previousRoute); 89 : } 90 : 91 5 : @override 92 : void didPush(Route route, Route? previousRoute) { 93 5 : super.didPush(route, previousRoute); 94 5 : _setCurrentRoute( 95 : route, 96 : checkAutoDispose: true, 97 : ); 98 : } 99 : 100 3 : @override 101 : void didReplace({Route? newRoute, Route? oldRoute}) { 102 3 : super.didReplace(newRoute: newRoute, oldRoute: oldRoute); 103 3 : _setCurrentRoute( 104 : newRoute, 105 : checkAutoDispose: true, 106 : ); 107 : } 108 : }