diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index b774279608..dcce4a8768 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -40,16 +40,15 @@ abstract class Route { /// Whether calling didPop() would return false. bool get willHandlePopInternally => false; - /// The given route has been pushed onto the navigator after this route. - void didPushNext(Route nextRoute) { } - /// The given route, which came after this one, has been popped off the /// navigator. void didPopNext(Route nextRoute) { } - /// The given old route, which was the route that came after this one, has - /// been replaced with the given new route. - void didReplaceNext(Route oldNextRoute, Route newNextRoute) { } + /// This route's next route has changed to the given new route. This is called + /// on a route whenever the next route changes for any reason, except for + /// cases when didPopNext() would be called, so long as it is in the history. + /// nextRoute will be null if there's no next route. + void didChangeNext(Route nextRoute) { } /// The route should remove its overlays and free any other resources. /// @@ -238,8 +237,9 @@ class NavigatorState extends State { route.install(_currentOverlayEntry); _history.add(route); route.didPush(); + route.didChangeNext(null); if (oldRoute != null) - oldRoute.didPushNext(route); + oldRoute.didChangeNext(route); config.observer?.didPush(route, oldRoute); }); assert(() { _debugLocked = false; return true; }); @@ -264,8 +264,12 @@ class NavigatorState extends State { newRoute.install(oldRoute.overlayEntries.last); _history[index] = newRoute; newRoute.didReplace(oldRoute); + if (index + 1 < _history.length) + newRoute.didChangeNext(_history[index + 1]); + else + newRoute.didChangeNext(null); if (index > 0) - _history[index - 1].didReplaceNext(oldRoute, newRoute); + _history[index - 1].didChangeNext(newRoute); oldRoute.dispose(); oldRoute._navigator = null; }); @@ -290,6 +294,9 @@ class NavigatorState extends State { assert(targetRoute.overlayEntries.isEmpty || !overlay.debugIsVisible(targetRoute.overlayEntries.last)); setState(() { _history.removeAt(index); + Route newRoute = index < _history.length ? _history[index] : null; + if (index > 0) + _history[index - 1].didChangeNext(newRoute); targetRoute.dispose(); targetRoute._navigator = null; }); @@ -378,17 +385,16 @@ class NavigatorTransaction { } /// Adds the given route to the Navigator's history, and transitions to it. - /// The route will have didPush() called on it; the previous route, if any, - /// will have didPushNext() called on it; and the Navigator observer, if any, - /// will have didPush() called on it. + /// The route will have didPush() and didChangeNext() called on it; the + /// previous route, if any, will have didChangeNext() called on it; and the + /// Navigator observer, if any, will have didPush() called on it. void push(Route route, { Set mostValuableKeys }) { assert(_debugOpen); _navigator._push(route, mostValuableKeys: mostValuableKeys); } - /// Replaces one given route with another, but does not call didPush/didPop. - /// Instead, this calls install() on the new route, then didReplace() on the - /// new route passing the old route, then dispose() on the old route. The + /// Replaces one given route with another. Calls install(), didReplace(), and + /// didChangeNext() on the new route, then dispose() on the old route. The /// navigator is not informed of the replacement. /// /// The old route must have overlay entries, otherwise we won't know where to @@ -416,8 +422,8 @@ class NavigatorTransaction { _navigator._replaceRouteBefore(anchorRoute: anchorRoute, newRoute: newRoute); } - /// Removes the route prior to the given anchorRoute without notifying - /// neighbouring routes or the navigator observer, if any. + /// Removes the route prior to the given anchorRoute, and calls didChangeNext + /// on the route prior to that one, if any. The observer is not notified. void removeRouteBefore(Route anchorRoute) { assert(_debugOpen); _navigator._removeRouteBefore(anchorRoute); @@ -426,7 +432,7 @@ class NavigatorTransaction { /// Tries to removes the current route, calling its didPop() method. If that /// method returns false, then nothing else happens. Otherwise, the observer /// (if any) is notified using its didPop() method, and the previous route is - /// notified using [Route.didPopNext]. + /// notified using [Route.didChangeNext]. /// /// The type of the result argument, if provided, must match the type argument /// of the class of the current route. (In practice, this is usually diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index b7f35c5909..fd7356cca2 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -123,6 +123,9 @@ abstract class TransitionRoute extends OverlayRoute { } } + PerformanceView get forwardPerformance => _forwardPerformance; + final ProxyPerformance _forwardPerformance = new ProxyPerformance(alwaysDismissedPerformance); + void install(OverlayEntry insertionPoint) { _performanceController = createPerformanceController(); assert(_performanceController != null); @@ -151,21 +154,17 @@ abstract class TransitionRoute extends OverlayRoute { return true; } - void finished() { - super.finished(); - _transitionCompleter?.complete(_result); + void didPopNext(Route nextRoute) { + _updateForwardPerformance(nextRoute); + super.didPopNext(nextRoute); } - void dispose() { - _performanceController.stop(); - super.dispose(); + void didChangeNext(Route nextRoute) { + _updateForwardPerformance(nextRoute); + super.didChangeNext(nextRoute); } - - PerformanceView get forwardPerformance => _forwardPerformance; - final ProxyPerformance _forwardPerformance = new ProxyPerformance(); - - void didPushNext(Route nextRoute) { + void _updateForwardPerformance(Route nextRoute) { if (nextRoute is TransitionRoute && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) { PerformanceView current = _forwardPerformance.masterPerformance; if (current != null) { @@ -189,13 +188,24 @@ abstract class TransitionRoute extends OverlayRoute { } else { _forwardPerformance.masterPerformance = nextRoute.performance; } + } else { + _forwardPerformance.masterPerformance = alwaysDismissedPerformance; } - super.didPushNext(nextRoute); } bool canTransitionTo(TransitionRoute nextRoute) => true; bool canTransitionFrom(TransitionRoute nextRoute) => true; + void finished() { + super.finished(); + _transitionCompleter?.complete(_result); + } + + void dispose() { + _performanceController.stop(); + super.dispose(); + } + String get debugLabel => '$runtimeType'; String toString() => '$runtimeType(performance: $_performanceController)'; } @@ -469,8 +479,8 @@ abstract class ModalRoute extends TransitionRoute with LocalHistoryRoute extends ModalRoute { PopupRoute({ Completer completer }) : super(completer: completer); bool get opaque => false; - void didPushNext(Route nextRoute) { + void didChangeNext(Route nextRoute) { assert(nextRoute is! PageRoute); - super.didPushNext(nextRoute); + super.didChangeNext(nextRoute); } } diff --git a/packages/unit/test/widget/routes_test.dart b/packages/unit/test/widget/routes_test.dart index 3be81ef170..65778dfc09 100644 --- a/packages/unit/test/widget/routes_test.dart +++ b/packages/unit/test/widget/routes_test.dart @@ -49,16 +49,12 @@ class TestRoute extends Route { return returnValue; } - void didPushNext(TestRoute nextRoute) { - log('didPushNext ${nextRoute.name}'); - } - void didPopNext(TestRoute nextRoute) { log('didPopNext ${nextRoute.name}'); } - void didReplaceNext(TestRoute oldNextRoute, TestRoute newNextRoute) { - log('didReplaceNext ${oldNextRoute.name} ${newNextRoute.name}'); + void didChangeNext(TestRoute nextRoute) { + log('didChangeNext ${nextRoute?.name}'); } void dispose() { @@ -100,6 +96,7 @@ void main() { [ 'initial: install', 'initial: didPush', + 'initial: didChangeNext null', ] ); TestRoute second; @@ -112,7 +109,8 @@ void main() { [ 'second: install', 'second: didPush', - 'initial: didPushNext second', + 'second: didChangeNext null', + 'initial: didChangeNext second', ] ); runNavigatorTest( @@ -124,7 +122,8 @@ void main() { [ 'third: install', 'third: didPush', - 'second: didPushNext third', + 'third: didChangeNext null', + 'second: didChangeNext third', ] ); runNavigatorTest( @@ -136,7 +135,8 @@ void main() { [ 'two: install', 'two: didReplace second', - 'initial: didReplaceNext second two', + 'two: didChangeNext third', + 'initial: didChangeNext two', 'second: dispose', ] ); @@ -187,6 +187,7 @@ void main() { [ 'first: install', 'first: didPush', + 'first: didChangeNext null', ] ); TestRoute second; @@ -199,7 +200,8 @@ void main() { [ 'second: install', 'second: didPush', - 'first: didPushNext second', + 'second: didChangeNext null', + 'first: didChangeNext second', ] ); runNavigatorTest( @@ -211,7 +213,8 @@ void main() { [ 'third: install', 'third: didPush', - 'second: didPushNext third', + 'third: didChangeNext null', + 'second: didChangeNext third', ] ); runNavigatorTest( @@ -245,7 +248,8 @@ void main() { [ 'three: install', 'three: didPush', - 'second: didPushNext three', + 'three: didChangeNext null', + 'second: didChangeNext three', ] ); TestRoute four; @@ -258,7 +262,8 @@ void main() { [ 'four: install', 'four: didPush', - 'three: didPushNext four', + 'four: didChangeNext null', + 'three: didChangeNext four', ] ); runNavigatorTest( @@ -268,6 +273,7 @@ void main() { transaction.removeRouteBefore(four); }, [ + 'second: didChangeNext four', 'three: dispose', ] ); @@ -306,6 +312,7 @@ void main() { [ 'A: install', 'A: didPush', + 'A: didChangeNext null', ] ); runNavigatorTest( @@ -317,7 +324,8 @@ void main() { [ 'B: install', 'B: didPush', - 'A: didPushNext B', + 'B: didChangeNext null', + 'A: didChangeNext B', ] ); TestRoute routeC; @@ -330,7 +338,8 @@ void main() { [ 'C: install', 'C: didPush', - 'B: didPushNext C', + 'C: didChangeNext null', + 'B: didChangeNext C', ] ); TestRoute routeB; @@ -343,7 +352,8 @@ void main() { [ 'b: install', 'b: didReplace B', - 'A: didReplaceNext B b', + 'b: didChangeNext C', + 'A: didChangeNext b', 'B: dispose', ] );