mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix crash if update pages right after a navigator pop (#68923)
This commit is contained in:
parent
27e1efc159
commit
6cfb86fbcb
@ -985,11 +985,15 @@ class DefaultTransitionDelegate<T> extends TransitionDelegate<T> {
|
||||
if (hasPagelessRoute) {
|
||||
final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute]!;
|
||||
for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
|
||||
assert(pagelessRoute.isWaitingForExitingDecision);
|
||||
if (isLastExitingPageRoute && pagelessRoute == pagelessRoutes.last) {
|
||||
pagelessRoute.markForPop(pagelessRoute.route.currentResult);
|
||||
} else {
|
||||
pagelessRoute.markForComplete(pagelessRoute.route.currentResult);
|
||||
// It is possible that a pageless route that belongs to an exiting
|
||||
// page-based route does not require exiting decision. This can
|
||||
// happen if the page list is updated right after a Navigator.pop.
|
||||
if (pagelessRoute.isWaitingForExitingDecision) {
|
||||
if (isLastExitingPageRoute && pagelessRoute == pagelessRoutes.last) {
|
||||
pagelessRoute.markForPop(pagelessRoute.route.currentResult);
|
||||
} else {
|
||||
pagelessRoute.markForComplete(pagelessRoute.route.currentResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3655,7 +3659,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
|
||||
() => <_RouteEntry>[],
|
||||
);
|
||||
pagelessRoutes.add(potentialEntryToRemove);
|
||||
if (previousOldPageRouteEntry!.isWaitingForExitingDecision)
|
||||
if (previousOldPageRouteEntry!.isWaitingForExitingDecision && potentialEntryToRemove.isPresent)
|
||||
potentialEntryToRemove.markNeedsExitingDecision();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3195,6 +3195,43 @@ void main() {
|
||||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can update pages before a pageless route has finished popping', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/68162.
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<Page<dynamic>> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name: 'second'),
|
||||
];
|
||||
bool onPopPage(Route<dynamic> route, dynamic result) {
|
||||
myPages.removeWhere((Page<dynamic> page) => route.settings == page);
|
||||
return route.didPop(result);
|
||||
}
|
||||
await tester.pumpWidget(
|
||||
buildNavigator(pages: myPages, onPopPage: onPopPage, key: navigator)
|
||||
);
|
||||
// Pushes a pageless route.
|
||||
showDialog<void>(
|
||||
useRootNavigator: false,
|
||||
context: navigator.currentContext!,
|
||||
builder: (BuildContext context) => const Text('dialog')
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('dialog'), findsOneWidget);
|
||||
// Pops the pageless route.
|
||||
navigator.currentState!.pop();
|
||||
// Before the pop finishes, updates the page list.
|
||||
myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
];
|
||||
await tester.pumpWidget(
|
||||
buildNavigator(pages: myPages, onPopPage: onPopPage, key: navigator)
|
||||
);
|
||||
// It should not crash the app.
|
||||
expect(tester.takeException(), isNull);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('pages remove and add trigger observer in the right order', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user