diff --git a/packages/flutter/lib/src/widgets/router.dart b/packages/flutter/lib/src/widgets/router.dart index 9032e78a0be..4b34a1f9f5b 100644 --- a/packages/flutter/lib/src/widgets/router.dart +++ b/packages/flutter/lib/src/widgets/router.dart @@ -298,10 +298,18 @@ class Router extends StatefulWidget { /// This method provides access to the delegates in the [Router]. For example, /// this can be used to access the [backButtonDispatcher] of the parent router /// when creating a [ChildBackButtonDispatcher] for a nested [Router]. - static Router? of(BuildContext context, {bool nullOk = false}) { + /// + /// If no [Router] ancestor exists for the given context, this will assert in + /// debug mode, and throw an exception in release mode. + /// + /// See also: + /// + /// * [maybeOf], which is a similar function, but it will return null instead + /// of throwing an exception if no [Router] ancestor exists. + static Router of(BuildContext context) { final _RouterScope? scope = context.dependOnInheritedWidgetOfExactType<_RouterScope>(); assert(() { - if (scope == null && !nullOk) { + if (scope == null) { 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 ' @@ -310,6 +318,24 @@ class Router extends StatefulWidget { } return true; }()); + return scope!.routerState.widget; + } + + /// Retrieves the immediate [Router] ancestor from the given context. + /// + /// This method provides access to the delegates in the [Router]. For example, + /// this can be used to access the [backButtonDispatcher] of the parent router + /// when creating a [ChildBackButtonDispatcher] for a nested [Router]. + /// + /// If no `Router` ancestor exists for the given context, this will return + /// null. + /// + /// See also: + /// + /// * [of], a similar method that returns a non-nullable value, and will + /// throw if no [Router] ancestor exists. + static Router? maybeOf(BuildContext context) { + final _RouterScope? scope = context.dependOnInheritedWidgetOfExactType<_RouterScope>(); return scope?.routerState.widget; } diff --git a/packages/flutter/test/widgets/router_test.dart b/packages/flutter/test/widgets/router_test.dart index 7ee0dce495d..ddf29ee3668 100644 --- a/packages/flutter/test/widgets/router_test.dart +++ b/packages/flutter/test/widgets/router_test.dart @@ -77,7 +77,7 @@ void main() { }); }); - testWidgets('Router.of can be null', (WidgetTester tester) async { + testWidgets('Router.maybeOf can be null', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); await tester.pumpWidget(buildBoilerPlate( Text('dummy', key: key) @@ -85,7 +85,7 @@ void main() { final BuildContext textContext = key.currentContext!; // This should not throw error. - Router? router = Router.of(textContext, nullOk: true); + Router? router = Router.maybeOf(textContext); expect(router, isNull); // Test when the nullOk is not specified.