Skip to content

Commit f86d108

Browse files
authored
Adds RouterConfig to simply API (#102786)
1 parent 02b300d commit f86d108

8 files changed

Lines changed: 536 additions & 85 deletions

File tree

packages/flutter/lib/src/cupertino/app.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,19 @@ class CupertinoApp extends StatefulWidget {
188188
routeInformationProvider = null,
189189
routeInformationParser = null,
190190
routerDelegate = null,
191-
backButtonDispatcher = null;
191+
backButtonDispatcher = null,
192+
routerConfig = null;
192193

193194
/// Creates a [CupertinoApp] that uses the [Router] instead of a [Navigator].
195+
///
196+
/// {@macro flutter.widgets.WidgetsApp.router}
194197
const CupertinoApp.router({
195198
super.key,
196199
this.routeInformationProvider,
197-
required RouteInformationParser<Object> this.routeInformationParser,
198-
required RouterDelegate<Object> this.routerDelegate,
200+
this.routeInformationParser,
201+
this.routerDelegate,
199202
this.backButtonDispatcher,
203+
this.routerConfig,
200204
this.theme,
201205
this.builder,
202206
this.title = '',
@@ -217,7 +221,8 @@ class CupertinoApp extends StatefulWidget {
217221
this.restorationScopeId,
218222
this.scrollBehavior,
219223
this.useInheritedMediaQuery = false,
220-
}) : assert(title != null),
224+
}) : assert(routerDelegate != null || routerConfig != null),
225+
assert(title != null),
221226
assert(showPerformanceOverlay != null),
222227
assert(checkerboardRasterCacheImages != null),
223228
assert(checkerboardOffscreenLayers != null),
@@ -282,6 +287,9 @@ class CupertinoApp extends StatefulWidget {
282287
/// {@macro flutter.widgets.widgetsApp.backButtonDispatcher}
283288
final BackButtonDispatcher? backButtonDispatcher;
284289

290+
/// {@macro flutter.widgets.widgetsApp.routerConfig}
291+
final RouterConfig<Object>? routerConfig;
292+
285293
/// {@macro flutter.widgets.widgetsApp.builder}
286294
final TransitionBuilder? builder;
287295

@@ -478,7 +486,7 @@ class CupertinoScrollBehavior extends ScrollBehavior {
478486

479487
class _CupertinoAppState extends State<CupertinoApp> {
480488
late HeroController _heroController;
481-
bool get _usesRouter => widget.routerDelegate != null;
489+
bool get _usesRouter => widget.routerDelegate != null || widget.routerConfig != null;
482490

483491
@override
484492
void initState() {
@@ -519,8 +527,9 @@ class _CupertinoAppState extends State<CupertinoApp> {
519527
return WidgetsApp.router(
520528
key: GlobalObjectKey(this),
521529
routeInformationProvider: widget.routeInformationProvider,
522-
routeInformationParser: widget.routeInformationParser!,
523-
routerDelegate: widget.routerDelegate!,
530+
routeInformationParser: widget.routeInformationParser,
531+
routerDelegate: widget.routerDelegate,
532+
routerConfig: widget.routerConfig,
524533
backButtonDispatcher: widget.backButtonDispatcher,
525534
builder: widget.builder,
526535
title: widget.title,

packages/flutter/lib/src/material/app.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,19 @@ class MaterialApp extends StatefulWidget {
248248
routeInformationProvider = null,
249249
routeInformationParser = null,
250250
routerDelegate = null,
251-
backButtonDispatcher = null;
251+
backButtonDispatcher = null,
252+
routerConfig = null;
252253

253254
/// Creates a [MaterialApp] that uses the [Router] instead of a [Navigator].
255+
///
256+
/// {@macro flutter.widgets.WidgetsApp.router}
254257
const MaterialApp.router({
255258
super.key,
256259
this.scaffoldMessengerKey,
257260
this.routeInformationProvider,
258-
required RouteInformationParser<Object> this.routeInformationParser,
259-
required RouterDelegate<Object> this.routerDelegate,
261+
this.routeInformationParser,
262+
this.routerDelegate,
263+
this.routerConfig,
260264
this.backButtonDispatcher,
261265
this.builder,
262266
this.title = '',
@@ -283,8 +287,7 @@ class MaterialApp extends StatefulWidget {
283287
this.restorationScopeId,
284288
this.scrollBehavior,
285289
this.useInheritedMediaQuery = false,
286-
}) : assert(routeInformationParser != null),
287-
assert(routerDelegate != null),
290+
}) : assert(routerDelegate != null || routerConfig != null),
288291
assert(title != null),
289292
assert(debugShowMaterialGrid != null),
290293
assert(showPerformanceOverlay != null),
@@ -353,6 +356,9 @@ class MaterialApp extends StatefulWidget {
353356
/// {@macro flutter.widgets.widgetsApp.backButtonDispatcher}
354357
final BackButtonDispatcher? backButtonDispatcher;
355358

359+
/// {@macro flutter.widgets.widgetsApp.routerConfig}
360+
final RouterConfig<Object>? routerConfig;
361+
356362
/// {@macro flutter.widgets.widgetsApp.builder}
357363
///
358364
/// Material specific features such as [showDialog] and [showMenu], and widgets
@@ -832,7 +838,7 @@ class MaterialScrollBehavior extends ScrollBehavior {
832838
class _MaterialAppState extends State<MaterialApp> {
833839
late HeroController _heroController;
834840

835-
bool get _usesRouter => widget.routerDelegate != null;
841+
bool get _usesRouter => widget.routerDelegate != null || widget.routerConfig != null;
836842

837843
@override
838844
void initState() {
@@ -925,8 +931,9 @@ class _MaterialAppState extends State<MaterialApp> {
925931
return WidgetsApp.router(
926932
key: GlobalObjectKey(this),
927933
routeInformationProvider: widget.routeInformationProvider,
928-
routeInformationParser: widget.routeInformationParser!,
929-
routerDelegate: widget.routerDelegate!,
934+
routeInformationParser: widget.routeInformationParser,
935+
routerDelegate: widget.routerDelegate,
936+
routerConfig: widget.routerConfig,
930937
backButtonDispatcher: widget.backButtonDispatcher,
931938
builder: _materialBuilder,
932939
title: widget.title,

packages/flutter/lib/src/widgets/app.dart

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)