3
3
// found in the LICENSE file.
4
4
5
5
import 'dart:async' ;
6
+ import 'dart:collection' ;
6
7
import 'dart:convert' ;
7
8
import 'dart:developer' as developer;
8
9
@@ -2335,7 +2336,7 @@ class _RouteEntry extends RouteTransitionRecord {
2335
2336
return page.canUpdate (routePage);
2336
2337
}
2337
2338
2338
- void handleAdd ({ @required NavigatorState navigator}) {
2339
+ void handleAdd ({ @required NavigatorState navigator, @required Route < dynamic > previousPresent }) {
2339
2340
assert (currentState == _RouteLifecycle .add);
2340
2341
assert (navigator != null );
2341
2342
assert (navigator._debugLocked);
@@ -2344,6 +2345,9 @@ class _RouteEntry extends RouteTransitionRecord {
2344
2345
route.install ();
2345
2346
assert (route.overlayEntries.isNotEmpty);
2346
2347
currentState = _RouteLifecycle .adding;
2348
+ navigator._observedRouteAdditions.add (
2349
+ _NavigatorPushObservation (route, previousPresent)
2350
+ );
2347
2351
}
2348
2352
2349
2353
void handlePush ({ @required NavigatorState navigator, @required bool isNewFirst, @required Route <dynamic > previous, @required Route <dynamic > previousPresent }) {
@@ -2377,12 +2381,14 @@ class _RouteEntry extends RouteTransitionRecord {
2377
2381
}
2378
2382
2379
2383
if (previousState == _RouteLifecycle .replace || previousState == _RouteLifecycle .pushReplace) {
2380
- for (final NavigatorObserver observer in navigator.widget.observers)
2381
- observer.didReplace (newRoute: route, oldRoute: previousPresent);
2384
+ navigator._observedRouteAdditions.add (
2385
+ _NavigatorReplaceObservation (route, previousPresent)
2386
+ );
2382
2387
} else {
2383
2388
assert (previousState == _RouteLifecycle .push);
2384
- for (final NavigatorObserver observer in navigator.widget.observers)
2385
- observer.didPush (route, previousPresent);
2389
+ navigator._observedRouteAdditions.add (
2390
+ _NavigatorPushObservation (route, previousPresent)
2391
+ );
2386
2392
}
2387
2393
}
2388
2394
@@ -2396,8 +2402,9 @@ class _RouteEntry extends RouteTransitionRecord {
2396
2402
assert (navigator._debugLocked);
2397
2403
assert (route._navigator == navigator);
2398
2404
currentState = _RouteLifecycle .popping;
2399
- for (final NavigatorObserver observer in navigator.widget.observers)
2400
- observer.didPop (route, previousPresent);
2405
+ navigator._observedRouteDeletions.add (
2406
+ _NavigatorPopObservation (route, previousPresent)
2407
+ );
2401
2408
}
2402
2409
2403
2410
void handleRemoval ({ @required NavigatorState navigator, @required Route <dynamic > previousPresent }) {
@@ -2406,21 +2413,20 @@ class _RouteEntry extends RouteTransitionRecord {
2406
2413
assert (route._navigator == navigator);
2407
2414
currentState = _RouteLifecycle .removing;
2408
2415
if (_reportRemovalToObserver) {
2409
- for (final NavigatorObserver observer in navigator.widget.observers)
2410
- observer.didRemove (route, previousPresent);
2416
+ navigator._observedRouteDeletions.add (
2417
+ _NavigatorRemoveObservation (route, previousPresent)
2418
+ );
2411
2419
}
2412
2420
}
2413
2421
2414
2422
bool doingPop = false ;
2415
2423
2416
- void didAdd ({ @required NavigatorState navigator, @required bool isNewFirst, @required Route < dynamic > previous, @required Route < dynamic > previousPresent }) {
2424
+ void didAdd ({ @required NavigatorState navigator, @required bool isNewFirst}) {
2417
2425
route.didAdd ();
2418
2426
currentState = _RouteLifecycle .idle;
2419
2427
if (isNewFirst) {
2420
2428
route.didChangeNext (null );
2421
2429
}
2422
- for (final NavigatorObserver observer in navigator.widget.observers)
2423
- observer.didPush (route, previousPresent);
2424
2430
}
2425
2431
2426
2432
void pop <T >(T result) {
@@ -2579,10 +2585,71 @@ class _RouteEntry extends RouteTransitionRecord {
2579
2585
}
2580
2586
}
2581
2587
2588
+ abstract class _NavigatorObservation {
2589
+ _NavigatorObservation (
2590
+ this .primaryRoute,
2591
+ this .secondaryRoute,
2592
+ );
2593
+ final Route <dynamic > primaryRoute;
2594
+ final Route <dynamic > secondaryRoute;
2595
+
2596
+ void notify (NavigatorObserver observer);
2597
+ }
2598
+
2599
+ class _NavigatorPushObservation extends _NavigatorObservation {
2600
+ _NavigatorPushObservation (
2601
+ Route <dynamic > primaryRoute,
2602
+ Route <dynamic > secondaryRoute
2603
+ ) : super (primaryRoute, secondaryRoute);
2604
+
2605
+ @override
2606
+ void notify (NavigatorObserver observer) {
2607
+ observer.didPush (primaryRoute, secondaryRoute);
2608
+ }
2609
+ }
2610
+
2611
+ class _NavigatorPopObservation extends _NavigatorObservation {
2612
+ _NavigatorPopObservation (
2613
+ Route <dynamic > primaryRoute,
2614
+ Route <dynamic > secondaryRoute
2615
+ ) : super (primaryRoute, secondaryRoute);
2616
+
2617
+ @override
2618
+ void notify (NavigatorObserver observer) {
2619
+ observer.didPop (primaryRoute, secondaryRoute);
2620
+ }
2621
+ }
2622
+
2623
+ class _NavigatorRemoveObservation extends _NavigatorObservation {
2624
+ _NavigatorRemoveObservation (
2625
+ Route <dynamic > primaryRoute,
2626
+ Route <dynamic > secondaryRoute
2627
+ ) : super (primaryRoute, secondaryRoute);
2628
+
2629
+ @override
2630
+ void notify (NavigatorObserver observer) {
2631
+ observer.didRemove (primaryRoute, secondaryRoute);
2632
+ }
2633
+ }
2634
+
2635
+ class _NavigatorReplaceObservation extends _NavigatorObservation {
2636
+ _NavigatorReplaceObservation (
2637
+ Route <dynamic > primaryRoute,
2638
+ Route <dynamic > secondaryRoute
2639
+ ) : super (primaryRoute, secondaryRoute);
2640
+
2641
+ @override
2642
+ void notify (NavigatorObserver observer) {
2643
+ observer.didReplace (newRoute: primaryRoute, oldRoute: secondaryRoute);
2644
+ }
2645
+ }
2646
+
2582
2647
/// The state for a [Navigator] widget.
2583
2648
class NavigatorState extends State <Navigator > with TickerProviderStateMixin {
2584
2649
final GlobalKey <OverlayState > _overlayKey = GlobalKey <OverlayState >();
2585
2650
List <_RouteEntry > _history = < _RouteEntry > [];
2651
+ final Queue <_NavigatorObservation > _observedRouteAdditions = Queue <_NavigatorObservation >();
2652
+ final Queue <_NavigatorObservation > _observedRouteDeletions = Queue <_NavigatorObservation >();
2586
2653
2587
2654
/// The [FocusScopeNode] for the [FocusScope] that encloses the routes.
2588
2655
final FocusScopeNode focusScopeNode = FocusScopeNode (debugLabel: 'Navigator Scope' );
@@ -2984,15 +3051,14 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
2984
3051
assert (rearrangeOverlay);
2985
3052
entry.handleAdd (
2986
3053
navigator: this ,
3054
+ previousPresent: _getRouteBefore (index - 1 , _RouteEntry .isPresentPredicate)? .route,
2987
3055
);
2988
3056
assert (entry.currentState == _RouteLifecycle .adding);
2989
3057
continue ;
2990
3058
case _RouteLifecycle .adding:
2991
3059
if (canRemoveOrAdd || next == null ) {
2992
3060
entry.didAdd (
2993
3061
navigator: this ,
2994
- previous: previous? .route,
2995
- previousPresent: _getRouteBefore (index - 1 , _RouteEntry .isPresentPredicate)? .route,
2996
3062
isNewFirst: next == null
2997
3063
);
2998
3064
assert (entry.currentState == _RouteLifecycle .idle);
@@ -3079,6 +3145,10 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
3079
3145
entry = previous;
3080
3146
previous = index > 0 ? _history[index - 1 ] : null ;
3081
3147
}
3148
+
3149
+ // Informs navigator observers about route changes.
3150
+ _flushObserverNotifications ();
3151
+
3082
3152
// Now that the list is clean, send the didChangeNext/didChangePrevious
3083
3153
// notifications.
3084
3154
_flushRouteAnnouncement ();
@@ -3102,6 +3172,23 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
3102
3172
overlay? .rearrange (_allRouteOverlayEntries);
3103
3173
}
3104
3174
3175
+ void _flushObserverNotifications () {
3176
+ if (widget.observers.isEmpty) {
3177
+ _observedRouteDeletions.clear ();
3178
+ _observedRouteAdditions.clear ();
3179
+ return ;
3180
+ }
3181
+ while (_observedRouteAdditions.isNotEmpty) {
3182
+ final _NavigatorObservation observation = _observedRouteAdditions.removeLast ();
3183
+ widget.observers.forEach (observation.notify);
3184
+ }
3185
+
3186
+ while (_observedRouteDeletions.isNotEmpty) {
3187
+ final _NavigatorObservation observation = _observedRouteDeletions.removeFirst ();
3188
+ widget.observers.forEach (observation.notify);
3189
+ }
3190
+ }
3191
+
3105
3192
void _flushRouteAnnouncement () {
3106
3193
int index = _history.length - 1 ;
3107
3194
while (index >= 0 ) {
0 commit comments