Skip to content

Commit

Permalink
Update Navigator updatePages() (#116945)
Browse files Browse the repository at this point in the history
* Update navigator.dart

* Update navigator.dart

* Add test

* Update navigator.dart

* lint

* Update packages/flutter/test/widgets/navigator_test.dart

Co-authored-by: chunhtai <[email protected]>

* Update packages/flutter/test/widgets/navigator_test.dart

Co-authored-by: chunhtai <[email protected]>

Co-authored-by: chunhtai <[email protected]>
  • Loading branch information
hannah-hyj and chunhtai authored Dec 15, 2022
1 parent 91c1c70 commit c98978a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 7 deletions.
21 changes: 14 additions & 7 deletions packages/flutter/lib/src/widgets/navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3687,30 +3687,37 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
oldEntriesBottom += 1;
}

int pagelessRoutesToSkip = 0;
final List<_RouteEntry> unattachedPagelessRoutes=<_RouteEntry>[];
// Scans the top of the list until we found a page-based route that cannot be
// updated.
while ((oldEntriesBottom <= oldEntriesTop) && (newPagesBottom <= newPagesTop)) {
final _RouteEntry oldEntry = _history[oldEntriesTop];
assert(oldEntry != null && oldEntry.currentState != _RouteLifecycle.disposed);
if (!oldEntry.pageBased) {
// This route might need to be skipped if we can not find a page above.
pagelessRoutesToSkip += 1;
unattachedPagelessRoutes.add(oldEntry);
oldEntriesTop -= 1;
continue;
}
final Page<dynamic> newPage = widget.pages[newPagesTop];
if (!oldEntry.canUpdateFrom(newPage)) {
break;
}
// We found the page for all the consecutive pageless routes below. Those
// pageless routes do not need to be skipped.
pagelessRoutesToSkip = 0;

// We found the page for all the consecutive pageless routes below. Attach these
// pageless routes to the page.
if(unattachedPagelessRoutes.isNotEmpty) {
pageRouteToPagelessRoutes.putIfAbsent(
oldEntry,
() => List<_RouteEntry>.from(unattachedPagelessRoutes),
);
unattachedPagelessRoutes.clear();
}

oldEntriesTop -= 1;
newPagesTop -= 1;
}
// Reverts the pageless routes that cannot be updated.
oldEntriesTop += pagelessRoutesToSkip;
oldEntriesTop += unattachedPagelessRoutes.length;

// Scans middle of the old entries and records the page key to old entry map.
int oldEntriesBottomToScan = oldEntriesBottom;
Expand Down
55 changes: 55 additions & 0 deletions packages/flutter/test/widgets/navigator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3342,6 +3342,61 @@ void main() {
expect(find.text('forth'), findsOneWidget);
});

//Regression test for https://github.com/flutter/flutter/issues/115887
testWidgets('Complex case 2', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
List<TestPage> 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),
);
expect(find.text('second'), findsOneWidget);
expect(find.text('initial'), findsNothing);
// Push pageless route to second page route
navigator.currentState!.push(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('second-pageless1'),
),
);

await tester.pumpAndSettle();
// Now the history should look like [initial, second, second-pageless1].
expect(find.text('initial'), findsNothing);
expect(find.text('second'), findsNothing);
expect(find.text('second-pageless1'), findsOneWidget);
expect(myPages.length, 2);

myPages = <TestPage>[
const TestPage(key: ValueKey<String>('2'), name:'second'),
];
await tester.pumpWidget(
buildNavigator(pages: myPages, onPopPage: onPopPage, key: navigator),
);
await tester.pumpAndSettle();

// Now the history should look like [second, second-pageless1].
expect(find.text('initial'), findsNothing);
expect(find.text('second'), findsNothing);
expect(find.text('second-pageless1'), findsOneWidget);
expect(myPages.length, 1);

// Pop the pageless route.
navigator.currentState!.pop();
await tester.pumpAndSettle();
expect(myPages.length, 1);
expect(find.text('initial'), findsNothing);
expect(find.text('second'), findsOneWidget);
expect(find.text('second-pageless1'), findsNothing);
});

testWidgets('complex case 1 - with always remove transition delegate', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
final AlwaysRemoveTransitionDelegate transitionDelegate = AlwaysRemoveTransitionDelegate();
Expand Down

0 comments on commit c98978a

Please sign in to comment.