From 345188d40e576ffb6c97fee60446af58b8c9965a Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Mon, 12 Oct 2020 09:32:07 -0700 Subject: [PATCH] make Router.of nullable (#67683) --- packages/flutter/lib/src/widgets/router.dart | 17 ++++++++++---- .../flutter/test/widgets/router_test.dart | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/widgets/router.dart b/packages/flutter/lib/src/widgets/router.dart index c6cf725307..abf6329887 100644 --- a/packages/flutter/lib/src/widgets/router.dart +++ b/packages/flutter/lib/src/widgets/router.dart @@ -302,10 +302,19 @@ class Router extends StatefulWidget { /// router to create a [ChildBackButtonDispatcher] for a nested router. /// Another use case may be updating the value in [routeInformationProvider] /// to navigate to a new route. - static Router of(BuildContext context) { - final _RouterScope scope = context.dependOnInheritedWidgetOfExactType<_RouterScope>()!; - assert(scope != null); - return scope.routerState.widget; + static Router? of(BuildContext context, {bool nullOk = false}) { + final _RouterScope? scope = context.dependOnInheritedWidgetOfExactType<_RouterScope>(); + assert(() { + if (scope == null && !nullOk) { + throw FlutterError( + 'Router operation requested with a context that does not include a Router.\n' + 'The context used to retrieve the Router must be that of a widget that ' + 'is a descendant of a Router widget.' + ); + } + return true; + }()); + return scope?.routerState.widget; } /// Forces the [Router] to run the [callback] and reports the route diff --git a/packages/flutter/test/widgets/router_test.dart b/packages/flutter/test/widgets/router_test.dart index a3c64def01..20343ddbd5 100644 --- a/packages/flutter/test/widgets/router_test.dart +++ b/packages/flutter/test/widgets/router_test.dart @@ -79,6 +79,28 @@ void main() { }); }); + testWidgets('Router.of can be null', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + await tester.pumpWidget(buildBoilerPlate( + Text('dummy', key: key) + )); + final BuildContext textContext = key.currentContext; + + // This should not throw error. + Router router = Router.of(textContext, nullOk: true); + expect(router, isNull); + + // Test when the nullOk is not specified. + bool hasFlutterError = false; + try { + router = Router.of(textContext); + } on FlutterError catch(e) { + expect(e.message.startsWith('Router'), isTrue); + hasFlutterError = true; + } + expect(hasFlutterError, isTrue); + }); + testWidgets('Simple router can handle pop route', (WidgetTester tester) async { final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); provider.value = const RouteInformation(