Skip to content

Commit 169c902

Browse files
committed
[go_router] Reduces excessive rebuilds due to inherited look up.
1 parent 25e1d87 commit 169c902

File tree

10 files changed

+145
-100
lines changed

10 files changed

+145
-100
lines changed

packages/go_router/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 9.0.0
2+
3+
- **BREAKING CHANGE**:
4+
- Removes GoRouter.location and GoRouter.canPop. Use GoRouterState.of().location and
5+
Navigator.of().canPop instead.
6+
- GoRouter does not `extends` ChangeNotifier.
7+
- [Migration guide](https://flutter.dev/go/go-router-v9-breaking-changes)
8+
- Reduces excessive rebuilds due to inherited look up.
9+
110
## 8.2.0
211

312
- Adds onException to GoRouter constructor.

packages/go_router/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ See the API documentation for details on the following topics:
3737
- [Error handling](https://pub.dev/documentation/go_router/latest/topics/Error%20handling-topic.html)
3838

3939
## Migration guides
40+
- [Migrating to 9.0.0](https://flutter.dev/go/go-router-v9-breaking-changes).
4041
- [Migrating to 8.0.0](https://flutter.dev/go/go-router-v8-breaking-changes).
4142
- [Migrating to 7.0.0](https://flutter.dev/go/go-router-v7-breaking-changes).
4243
- [Migrating to 6.0.0](https://flutter.dev/go/go-router-v6-breaking-changes)

packages/go_router/lib/src/information_provider.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ class GoRouteInformationProvider extends RouteInformationProvider
133133
RouteInformation get value => _value;
134134
RouteInformation _value;
135135

136+
@override
137+
// TODO(chunhtai): remove this ignore once package minimum dart version is
138+
// above 3.
139+
// ignore: unnecessary_overrides
140+
void notifyListeners() {
141+
super.notifyListeners();
142+
}
143+
136144
void _setValue(String location, Object state) {
137145
final bool shouldNotify =
138146
_value.location != location || _value.state != state;

packages/go_router/lib/src/misc/inherited_router.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import '../router.dart';
1111
///
1212
/// Used for to find the current GoRouter in the widget tree. This is useful
1313
/// when routing from anywhere in your app.
14-
class InheritedGoRouter extends InheritedNotifier<GoRouter> {
14+
class InheritedGoRouter extends InheritedWidget {
1515
/// Default constructor for the inherited go router.
1616
const InheritedGoRouter({
1717
required super.child,
1818
required this.goRouter,
1919
super.key,
20-
}) : super(notifier: goRouter);
20+
});
2121

2222
/// The [GoRouter] that is made available to the widget tree.
2323
final GoRouter goRouter;
@@ -27,4 +27,7 @@ class InheritedGoRouter extends InheritedNotifier<GoRouter> {
2727
super.debugFillProperties(properties);
2828
properties.add(DiagnosticsProperty<GoRouter>('goRouter', goRouter));
2929
}
30+
31+
@override
32+
bool updateShouldNotify(covariant InheritedWidget oldWidget) => false;
3033
}

packages/go_router/lib/src/router.dart

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ typedef GoExceptionHandler = void Function(
6262
/// {@category Deep linking}
6363
/// {@category Error handling}
6464
/// {@category Named routes}
65-
class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
65+
class GoRouter implements RouterConfig<RouteMatchList> {
6666
/// Default constructor to configure a GoRouter with a routes builder
6767
/// and an error page builder.
6868
///
@@ -152,7 +152,6 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
152152
builderWithNav: (BuildContext context, Widget child) =>
153153
InheritedGoRouter(goRouter: this, child: child),
154154
);
155-
routerDelegate.addListener(_handleStateMayChange);
156155

157156
assert(() {
158157
log.info('setting initial location $initialLocation');
@@ -296,34 +295,9 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
296295
@override
297296
late final GoRouteInformationParser routeInformationParser;
298297

299-
/// Gets the current location.
300-
// TODO(chunhtai): deprecates this once go_router_builder is migrated to
301-
// GoRouterState.of.
302-
String get location => _location;
303-
String _location = '/';
304-
305298
/// Returns `true` if there is at least two or more route can be pop.
306299
bool canPop() => routerDelegate.canPop();
307300

308-
void _handleStateMayChange() {
309-
final String newLocation;
310-
if (routerDelegate.currentConfiguration.isNotEmpty &&
311-
routerDelegate.currentConfiguration.matches.last
312-
is ImperativeRouteMatch) {
313-
newLocation = (routerDelegate.currentConfiguration.matches.last
314-
as ImperativeRouteMatch)
315-
.matches
316-
.uri
317-
.toString();
318-
} else {
319-
newLocation = routerDelegate.currentConfiguration.uri.toString();
320-
}
321-
if (_location != newLocation) {
322-
_location = newLocation;
323-
notifyListeners();
324-
}
325-
}
326-
327301
/// Get a location from route name and parameters.
328302
/// This is useful for redirecting to a named location.
329303
String namedLocation(
@@ -488,7 +462,7 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
488462
/// of any GoRoute under it.
489463
void pop<T extends Object?>([T? result]) {
490464
assert(() {
491-
log.info('popping $location');
465+
log.info('popping ${routerDelegate.currentConfiguration.uri}');
492466
return true;
493467
}());
494468
routerDelegate.pop<T>(result);
@@ -497,7 +471,7 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
497471
/// Refresh the route.
498472
void refresh() {
499473
assert(() {
500-
log.info('refreshing $location');
474+
log.info('refreshing ${routerDelegate.currentConfiguration.uri}');
501475
return true;
502476
}());
503477
routeInformationProvider.notifyListeners();
@@ -507,8 +481,7 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
507481
///
508482
/// This method throws when it is called during redirects.
509483
static GoRouter of(BuildContext context) {
510-
final InheritedGoRouter? inherited =
511-
context.dependOnInheritedWidgetOfExactType<InheritedGoRouter>();
484+
final InheritedGoRouter? inherited = maybeOf(context);
512485
assert(inherited != null, 'No GoRouter found in context');
513486
return inherited!.goRouter;
514487
}
@@ -517,17 +490,16 @@ class GoRouter extends ChangeNotifier implements RouterConfig<RouteMatchList> {
517490
///
518491
/// This method returns null when it is called during redirects.
519492
static GoRouter? maybeOf(BuildContext context) {
520-
final InheritedGoRouter? inherited =
521-
context.dependOnInheritedWidgetOfExactType<InheritedGoRouter>();
493+
final InheritedGoRouter? inherited = context
494+
.getElementForInheritedWidgetOfExactType<InheritedGoRouter>()
495+
?.widget as InheritedGoRouter?;
522496
return inherited?.goRouter;
523497
}
524498

525-
@override
499+
/// Disposes resource created by this object.
526500
void dispose() {
527501
routeInformationProvider.dispose();
528-
routerDelegate.removeListener(_handleStateMayChange);
529502
routerDelegate.dispose();
530-
super.dispose();
531503
}
532504

533505
String _effectiveInitialLocation(String? initialLocation) {

packages/go_router/pubspec.yaml

Lines changed: 1 addition & 1 deletion
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: 8.2.0
4+
version: 9.0.0
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/extension_test.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/material.dart';
66
import 'package:flutter_test/flutter_test.dart';
77
import 'package:go_router/go_router.dart';
8+
import 'package:go_router/src/match.dart';
89

910
void main() {
1011
group('replaceNamed', () {
@@ -37,7 +38,10 @@ void main() {
3738
final GoRouter router = await createGoRouter(tester);
3839
await tester.tap(find.text('Settings'));
3940
await tester.pumpAndSettle();
40-
expect(router.location, '/page-0/settings?search=notification');
41+
final ImperativeRouteMatch routeMatch = router
42+
.routerDelegate.currentConfiguration.last as ImperativeRouteMatch;
43+
expect(routeMatch.matches.uri.toString(),
44+
'/page-0/settings?search=notification');
4145
});
4246
});
4347
}

0 commit comments

Comments
 (0)