Skip to content

Commit 871cd47

Browse files
authored
[go_router] Fixes an issue where android back button pops wrong page. (#7348)
fixes flutter/flutter#141906
1 parent 9cc09f1 commit 871cd47

File tree

5 files changed

+87
-23
lines changed

5 files changed

+87
-23
lines changed

packages/go_router/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 14.2.5
2+
3+
- Fixes an issue where android back button pops pages in the wrong order.
4+
15
## 14.2.4
26

37
- Updates minimum supported SDK version to Flutter 3.19/Dart 3.3.

packages/go_router/lib/src/delegate.dart

+20-21
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
5252

5353
@override
5454
Future<bool> popRoute() async {
55-
NavigatorState? state = navigatorKey.currentState;
56-
if (state == null) {
57-
return false;
58-
}
59-
if (!state.canPop()) {
60-
state = null;
61-
}
62-
RouteMatchBase walker = currentConfiguration.matches.last;
63-
while (walker is ShellRouteMatch) {
64-
if (walker.navigatorKey.currentState?.canPop() ?? false) {
65-
state = walker.navigatorKey.currentState;
66-
}
67-
walker = walker.matches.last;
68-
}
69-
assert(walker is RouteMatch);
55+
final NavigatorState? state = _findCurrentNavigator();
7056
if (state != null) {
7157
return state.maybePop();
7258
}
@@ -75,7 +61,8 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
7561
if (lastRoute.onExit != null && navigatorKey.currentContext != null) {
7662
return !(await lastRoute.onExit!(
7763
navigatorKey.currentContext!,
78-
walker.buildState(_configuration, currentConfiguration),
64+
currentConfiguration.last
65+
.buildState(_configuration, currentConfiguration),
7966
));
8067
}
8168
return false;
@@ -98,21 +85,33 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
9885

9986
/// Pops the top-most route.
10087
void pop<T extends Object?>([T? result]) {
88+
final NavigatorState? state = _findCurrentNavigator();
89+
if (state == null) {
90+
throw GoError('There is nothing to pop');
91+
}
92+
state.pop(result);
93+
}
94+
95+
NavigatorState? _findCurrentNavigator() {
10196
NavigatorState? state;
10297
if (navigatorKey.currentState?.canPop() ?? false) {
10398
state = navigatorKey.currentState;
10499
}
105100
RouteMatchBase walker = currentConfiguration.matches.last;
106101
while (walker is ShellRouteMatch) {
107-
if (walker.navigatorKey.currentState?.canPop() ?? false) {
102+
final NavigatorState potentialCandidate =
103+
walker.navigatorKey.currentState!;
104+
if (!ModalRoute.of(potentialCandidate.context)!.isCurrent) {
105+
// There is a pageless route on top of the shell route. it needs to be
106+
// popped first.
107+
break;
108+
}
109+
if (potentialCandidate.canPop()) {
108110
state = walker.navigatorKey.currentState;
109111
}
110112
walker = walker.matches.last;
111113
}
112-
if (state == null) {
113-
throw GoError('There is nothing to pop');
114-
}
115-
state.pop(result);
114+
return state;
116115
}
117116

118117
void _debugAssertMatchListNotEmpty() {

packages/go_router/lib/src/router.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class GoRouter implements RouterConfig<RouteMatchList> {
199199
setLogging(enabled: debugLogDiagnostics);
200200
WidgetsFlutterBinding.ensureInitialized();
201201

202-
navigatorKey ??= GlobalKey<NavigatorState>();
202+
navigatorKey ??= GlobalKey<NavigatorState>(debugLabel: 'root');
203203

204204
_routingConfig.addListener(_handleRoutingConfigChanged);
205205
configuration = RouteConfiguration(

packages/go_router/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: go_router
22
description: A declarative router for Flutter based on Navigation 2 supporting
33
deep linking, data-driven routes and more
4-
version: 14.2.4
4+
version: 14.2.5
55
repository: https://github.com/flutter/packages/tree/main/packages/go_router
66
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
77

packages/go_router/test/go_router_test.dart

+61
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,67 @@ void main() {
398398
expect(find.byKey(settings), findsOneWidget);
399399
});
400400

401+
testWidgets('android back button pop in correct order',
402+
(WidgetTester tester) async {
403+
// Regression test for https://github.com/flutter/flutter/issues/141906.
404+
final List<RouteBase> routes = <RouteBase>[
405+
GoRoute(
406+
path: '/',
407+
builder: (_, __) => const Text('home'),
408+
routes: <RouteBase>[
409+
ShellRoute(
410+
builder: (
411+
BuildContext context,
412+
GoRouterState state,
413+
Widget child,
414+
) {
415+
return Column(
416+
children: <Widget>[
417+
const Text('shell'),
418+
child,
419+
],
420+
);
421+
},
422+
routes: <GoRoute>[
423+
GoRoute(
424+
path: 'page',
425+
builder: (BuildContext context, __) {
426+
return TextButton(
427+
onPressed: () {
428+
Navigator.of(context, rootNavigator: true).push(
429+
MaterialPageRoute<void>(
430+
builder: (BuildContext context) {
431+
return const Text('pageless');
432+
}),
433+
);
434+
},
435+
child: const Text('page'),
436+
);
437+
},
438+
),
439+
],
440+
),
441+
]),
442+
];
443+
final GoRouter router =
444+
await createRouter(routes, tester, initialLocation: '/page');
445+
expect(find.text('shell'), findsOneWidget);
446+
expect(find.text('page'), findsOneWidget);
447+
448+
await tester.tap(find.text('page'));
449+
await tester.pumpAndSettle();
450+
expect(find.text('shell'), findsNothing);
451+
expect(find.text('page'), findsNothing);
452+
expect(find.text('pageless'), findsOneWidget);
453+
454+
final bool result = await router.routerDelegate.popRoute();
455+
expect(result, isTrue);
456+
await tester.pumpAndSettle();
457+
expect(find.text('shell'), findsOneWidget);
458+
expect(find.text('page'), findsOneWidget);
459+
expect(find.text('pageless'), findsNothing);
460+
});
461+
401462
testWidgets('can correctly pop stacks of repeated pages',
402463
(WidgetTester tester) async {
403464
// Regression test for https://github.com/flutter/flutter/issues/#132229.

0 commit comments

Comments
 (0)