@@ -399,15 +399,23 @@ class WidgetsApp extends StatefulWidget {
399399 routeInformationProvider = null ,
400400 routeInformationParser = null ,
401401 routerDelegate = null ,
402- backButtonDispatcher = null ;
402+ backButtonDispatcher = null ,
403+ routerConfig = null ;
403404
404405 /// Creates a [WidgetsApp] that uses the [Router] instead of a [Navigator] .
406+ ///
407+ /// {@template flutter.widgets.WidgetsApp.router}
408+ /// If the [routerConfig] is provided, the other router related delegates,
409+ /// [routeInformationParser] , [routeInformationProvider] , [routerDelegate] ,
410+ /// and [backButtonDispatcher] , must all be null.
411+ /// {@endtemplate}
405412 WidgetsApp .router ({
406413 super .key,
407414 this .routeInformationProvider,
408- required RouteInformationParser <Object > this .routeInformationParser,
409- required RouterDelegate <Object > this .routerDelegate,
410- BackButtonDispatcher ? backButtonDispatcher,
415+ this .routeInformationParser,
416+ this .routerDelegate,
417+ this .routerConfig,
418+ this .backButtonDispatcher,
411419 this .builder,
412420 this .title = '' ,
413421 this .onGenerateTitle,
@@ -429,11 +437,21 @@ class WidgetsApp extends StatefulWidget {
429437 this .actions,
430438 this .restorationScopeId,
431439 this .useInheritedMediaQuery = false ,
432- }) : assert (
433- routeInformationParser != null &&
434- routerDelegate != null ,
435- 'The routeInformationParser and routerDelegate cannot be null.' ,
436- ),
440+ }) : assert ((){
441+ if (routerConfig != null ) {
442+ assert (
443+ (routeInformationProvider ?? routeInformationParser ?? routerDelegate ?? backButtonDispatcher) == null ,
444+ 'If the routerConfig is provided, all the other router delegates must not be provided' ,
445+ );
446+ return true ;
447+ }
448+ assert (routerDelegate != null , 'Either one of routerDelegate or routerConfig must be provided' );
449+ assert (
450+ routeInformationProvider == null || routeInformationParser != null ,
451+ 'If routeInformationProvider is provided, routeInformationParser must also be provided' ,
452+ );
453+ return true ;
454+ }()),
437455 assert (title != null ),
438456 assert (color != null ),
439457 assert (supportedLocales != null && supportedLocales.isNotEmpty),
@@ -444,7 +462,6 @@ class WidgetsApp extends StatefulWidget {
444462 assert (debugShowCheckedModeBanner != null ),
445463 assert (debugShowWidgetInspector != null ),
446464 navigatorObservers = null ,
447- backButtonDispatcher = backButtonDispatcher ?? RootBackButtonDispatcher (),
448465 navigatorKey = null ,
449466 onGenerateRoute = null ,
450467 pageRouteBuilder = null ,
@@ -524,7 +541,7 @@ class WidgetsApp extends StatefulWidget {
524541 ///
525542 /// See also:
526543 ///
527- /// * [Router.routeInformationParser] : which receives this object when this
544+ /// * [Router.routeInformationParser] , which receives this object when this
528545 /// widget builds the [Router].
529546 /// {@endtemplate}
530547 final RouteInformationParser <Object >? routeInformationParser;
@@ -540,7 +557,7 @@ class WidgetsApp extends StatefulWidget {
540557 ///
541558 /// See also:
542559 ///
543- /// * [Router.routerDelegate] : which receives this object when this widget
560+ /// * [Router.routerDelegate] , which receives this object when this widget
544561 /// builds the [Router].
545562 /// {@endtemplate}
546563 final RouterDelegate <Object >? routerDelegate;
@@ -555,7 +572,7 @@ class WidgetsApp extends StatefulWidget {
555572 ///
556573 /// See also:
557574 ///
558- /// * [Router.backButtonDispatcher] : which receives this object when this
575+ /// * [Router.backButtonDispatcher] , which receives this object when this
559576 /// widget builds the [Router].
560577 /// {@endtemplate}
561578 final BackButtonDispatcher ? backButtonDispatcher;
@@ -573,11 +590,25 @@ class WidgetsApp extends StatefulWidget {
573590 ///
574591 /// See also:
575592 ///
576- /// * [Router.routeInformationProvider] : which receives this object when this
593+ /// * [Router.routeInformationProvider] , which receives this object when this
577594 /// widget builds the [Router].
578595 /// {@endtemplate}
579596 final RouteInformationProvider ? routeInformationProvider;
580597
598+ /// {@template flutter.widgets.widgetsApp.routerConfig}
599+ /// An object to configure the underlying [Router] .
600+ ///
601+ /// If the [routerConfig] is provided, the other router related delegates,
602+ /// [routeInformationParser] , [routeInformationProvider] , [routerDelegate] ,
603+ /// and [backButtonDispatcher] , must all be null.
604+ ///
605+ /// See also:
606+ ///
607+ /// * [Router.withConfig] , which receives this object when this
608+ /// widget builds the [Router].
609+ /// {@endtemplate}
610+ final RouterConfig <Object >? routerConfig;
611+
581612 /// {@template flutter.widgets.widgetsApp.home}
582613 /// The widget for the default route of the app ([Navigator.defaultRouteName] ,
583614 /// which is `/` ).
@@ -1295,42 +1326,53 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
12951326 super .dispose ();
12961327 }
12971328
1329+ void _clearRouterResource () {
1330+ _defaultRouteInformationProvider? .dispose ();
1331+ _defaultRouteInformationProvider = null ;
1332+ _defaultBackButtonDispatcher = null ;
1333+ }
1334+
1335+ void _clearNavigatorResource () {
1336+ _navigator = null ;
1337+ }
1338+
12981339 void _updateRouting ({WidgetsApp ? oldWidget}) {
1299- if (_usesRouter) {
1300- assert (! _usesNavigator);
1301- _navigator = null ;
1302- if (oldWidget == null || oldWidget.routeInformationProvider != widget.routeInformationProvider) {
1340+ if (_usesRouterWithDelegates) {
1341+ assert (! _usesNavigator && ! _usesRouterWithConfig);
1342+ _clearNavigatorResource ();
1343+ if (widget.routeInformationProvider == null && widget.routeInformationParser != null ) {
1344+ _defaultRouteInformationProvider ?? = PlatformRouteInformationProvider (
1345+ initialRouteInformation: RouteInformation (
1346+ location: _initialRouteName,
1347+ ),
1348+ );
1349+ } else {
13031350 _defaultRouteInformationProvider? .dispose ();
13041351 _defaultRouteInformationProvider = null ;
1305- if (widget.routeInformationProvider == null ) {
1306- _defaultRouteInformationProvider = PlatformRouteInformationProvider (
1307- initialRouteInformation: RouteInformation (
1308- location: _initialRouteName,
1309- ),
1310- );
1311- }
13121352 }
1353+ if (widget.backButtonDispatcher == null ) {
1354+ _defaultBackButtonDispatcher ?? = RootBackButtonDispatcher ();
1355+ }
1356+
13131357 } else if (_usesNavigator) {
1314- assert (! _usesRouter);
1315- _defaultRouteInformationProvider? .dispose ();
1316- _defaultRouteInformationProvider = null ;
1358+ assert (! _usesRouterWithDelegates && ! _usesRouterWithConfig);
1359+ _clearRouterResource ();
13171360 if (_navigator == null || widget.navigatorKey != oldWidget! .navigatorKey) {
13181361 _navigator = widget.navigatorKey ?? GlobalObjectKey <NavigatorState >(this );
13191362 }
13201363 assert (_navigator != null );
13211364 } else {
1322- assert (widget.builder != null );
1323- assert (! _usesRouter);
1324- assert (! _usesNavigator);
1325- _navigator = null ;
1326- _defaultRouteInformationProvider? .dispose ();
1327- _defaultRouteInformationProvider = null ;
1365+ assert (widget.builder != null || _usesRouterWithConfig);
1366+ assert (! _usesRouterWithDelegates && ! _usesNavigator);
1367+ _clearRouterResource ();
1368+ _clearNavigatorResource ();
13281369 }
13291370 // If we use a navigator, we have a navigator key.
13301371 assert (_usesNavigator == (_navigator != null ));
13311372 }
13321373
1333- bool get _usesRouter => widget.routerDelegate != null ;
1374+ bool get _usesRouterWithDelegates => widget.routerDelegate != null ;
1375+ bool get _usesRouterWithConfig => widget.routerConfig != null ;
13341376 bool get _usesNavigator => widget.home != null
13351377 || (widget.routes? .isNotEmpty ?? false )
13361378 || widget.onGenerateRoute != null
@@ -1340,6 +1382,8 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
13401382
13411383 RouteInformationProvider ? get _effectiveRouteInformationProvider => widget.routeInformationProvider ?? _defaultRouteInformationProvider;
13421384 PlatformRouteInformationProvider ? _defaultRouteInformationProvider;
1385+ BackButtonDispatcher get _effectiveBackButtonDispatcher => widget.backButtonDispatcher ?? _defaultBackButtonDispatcher! ;
1386+ RootBackButtonDispatcher ? _defaultBackButtonDispatcher;
13431387
13441388 // NAVIGATOR
13451389
@@ -1409,7 +1453,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
14091453 assert (mounted);
14101454 // The back button dispatcher should handle the pop route if we use a
14111455 // router.
1412- if (_usesRouter )
1456+ if (_usesRouterWithDelegates )
14131457 return false ;
14141458
14151459 final NavigatorState ? navigator = _navigator? .currentState;
@@ -1423,7 +1467,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
14231467 assert (mounted);
14241468 // The route name provider should handle the push route if we uses a
14251469 // router.
1426- if (_usesRouter )
1470+ if (_usesRouterWithDelegates )
14271471 return false ;
14281472
14291473 final NavigatorState ? navigator = _navigator? .currentState;
@@ -1535,14 +1579,13 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
15351579 @override
15361580 Widget build (BuildContext context) {
15371581 Widget ? routing;
1538- if (_usesRouter) {
1539- assert (_effectiveRouteInformationProvider != null );
1582+ if (_usesRouterWithDelegates) {
15401583 routing = Router <Object >(
15411584 restorationScopeId: 'router' ,
15421585 routeInformationProvider: _effectiveRouteInformationProvider,
15431586 routeInformationParser: widget.routeInformationParser,
15441587 routerDelegate: widget.routerDelegate! ,
1545- backButtonDispatcher: widget.backButtonDispatcher ,
1588+ backButtonDispatcher: _effectiveBackButtonDispatcher ,
15461589 );
15471590 } else if (_usesNavigator) {
15481591 assert (_navigator != null );
@@ -1560,6 +1603,11 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
15601603 observers: widget.navigatorObservers! ,
15611604 reportsRouteUpdateToEngine: true ,
15621605 );
1606+ } else if (_usesRouterWithConfig) {
1607+ routing = Router <Object >.withConfig (
1608+ restorationScopeId: 'router' ,
1609+ config: widget.routerConfig! ,
1610+ );
15631611 }
15641612
15651613 Widget result;
0 commit comments