Unverified Commit 38c33d9c authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Build routes even less. (#58202)

parent eee3912f
......@@ -185,7 +185,6 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
break;
}
changedInternalState();
}
@override
......@@ -193,16 +192,19 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
assert(!_transitionCompleter.isCompleted, 'Cannot install a $runtimeType after disposing it.');
_controller = createAnimationController();
assert(_controller != null, '$runtimeType.createAnimationController() returned null.');
_animation = createAnimation();
_animation = createAnimation()
..addStatusListener(_handleStatusChanged);
assert(_animation != null, '$runtimeType.createAnimation() returned null.');
super.install();
if (_animation.isCompleted && overlayEntries.isNotEmpty) {
overlayEntries.first.opaque = opaque;
}
}
@override
TickerFuture didPush() {
assert(_controller != null, '$runtimeType.didPush called before calling install() or after calling dispose().');
assert(!_transitionCompleter.isCompleted, 'Cannot reuse a $runtimeType after disposing it.');
_didPushOrReplace();
super.didPush();
return _controller.forward();
}
......@@ -211,7 +213,6 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
void didAdd() {
assert(_controller != null, '$runtimeType.didPush called before calling install() or after calling dispose().');
assert(!_transitionCompleter.isCompleted, 'Cannot reuse a $runtimeType after disposing it.');
_didPushOrReplace();
super.didAdd();
_controller.value = _controller.upperBound;
}
......@@ -222,19 +223,9 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
assert(!_transitionCompleter.isCompleted, 'Cannot reuse a $runtimeType after disposing it.');
if (oldRoute is TransitionRoute)
_controller.value = oldRoute._controller.value;
_didPushOrReplace();
super.didReplace(oldRoute);
}
void _didPushOrReplace() {
_animation.addStatusListener(_handleStatusChanged);
// If the animation is already completed, _handleStatusChanged will not get
// a chance to set opaqueness of OverlayEntry.
if (_animation.isCompleted && overlayEntries.isNotEmpty) {
overlayEntries.first.opaque = opaque;
}
}
@override
bool didPop(T result) {
assert(_controller != null, '$runtimeType.didPop called before calling install() or after calling dispose().');
......@@ -856,7 +847,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// ```
///
/// The given [BuildContext] will be rebuilt if the state of the route changes
/// (specifically, if [isCurrent] or [canPop] change value).
/// while it is visible (specifically, if [isCurrent] or [canPop] change value).
@optionalTypeArgs
static ModalRoute<T> of<T extends Object>(BuildContext context) {
final _ModalScopeStatus widget = context.dependOnInheritedWidgetOfExactType<_ModalScopeStatus>();
......@@ -936,7 +927,8 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// is not wrapped in any transition widgets.
///
/// The [buildTransitions] method, in contrast to [buildPage], is called each
/// time the [Route]'s state changes (e.g. the value of [canPop]).
/// time the [Route]'s state changes while it is visible (e.g. if the value of
/// [canPop] changes on the active route).
///
/// The [buildTransitions] method is typically used to define transitions
/// that animate the new topmost route's comings and goings. When the
......@@ -1392,8 +1384,9 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// Whether this route can be popped.
///
/// When this changes, the route will rebuild, and any widgets that used
/// [ModalRoute.of] will be notified.
/// When this changes, if the route is visible, the route will
/// rebuild, and any widgets that used [ModalRoute.of] will be
/// notified.
bool get canPop => !isFirst || willHandlePopInternally;
// Internals
......
......@@ -1182,7 +1182,50 @@ void main() {
expect(log, <String>['building B', 'building C', 'found C', 'building D']);
key.currentState.pop<void>();
await tester.pumpAndSettle(const Duration(milliseconds: 10));
expect(log, <String>['building B', 'building C', 'found C', 'building D', 'building C', 'found C']);
expect(log, <String>['building B', 'building C', 'found C', 'building D']);
});
testWidgets('Routes don\'t rebuild just because their animations ended', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
final List<String> log = <String>[];
Route<dynamic> nextRoute = PageRouteBuilder<int>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
log.add('building page 1 - ${ModalRoute.of(context).canPop}');
return const Placeholder();
},
);
await tester.pumpWidget(MaterialApp(
navigatorKey: key,
onGenerateRoute: (RouteSettings settings) {
assert(nextRoute != null);
final Route<dynamic> result = nextRoute;
nextRoute = null;
return result;
},
));
expect(log, <String>['building page 1 - false']);
key.currentState.pushReplacement(PageRouteBuilder<int>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
log.add('building page 2 - ${ModalRoute.of(context).canPop}');
return const Placeholder();
},
));
expect(log, <String>['building page 1 - false']);
await tester.pump();
expect(log, <String>['building page 1 - false', 'building page 2 - false']);
await tester.pump(const Duration(milliseconds: 150));
expect(log, <String>['building page 1 - false', 'building page 2 - false']);
key.currentState.pushReplacement(PageRouteBuilder<int>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
log.add('building page 3 - ${ModalRoute.of(context).canPop}');
return const Placeholder();
},
));
expect(log, <String>['building page 1 - false', 'building page 2 - false']);
await tester.pump();
expect(log, <String>['building page 1 - false', 'building page 2 - false', 'building page 3 - false']);
await tester.pump(const Duration(milliseconds: 200));
expect(log, <String>['building page 1 - false', 'building page 2 - false', 'building page 3 - false']);
});
testWidgets('route semantics', (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment