setNewRoutePath method
SynchronousFuture<void>
setNewRoutePath(
- covariant AdvancedRouteInformation configuration
override
Called by the Router when the Router.routeInformationProvider reports that a new route has been pushed to the application by the operating system.
Consider using a SynchronousFuture if the result can be computed synchronously, so that the Router does not need to wait for the next microtask to schedule a build.
Implementation
@override
SynchronousFuture<void> setNewRoutePath(
covariant AdvancedRouteInformation configuration) {
if (configuration == _currentInternalPath) {
return SynchronousFuture(null);
}
List<Page>? changedPages;
AdvancedRouteInformation? currentInternalPath;
AdvancedRouteInformation? currentNestedPath;
// check for match in paths map
if (paths.isNotEmpty) {
// find matching reference
var uri = Uri.parse(configuration.location ?? '');
var query = uri.query;
var path = uri.path;
if (path.isEmpty) {
path = initialLocation;
}
PathGroup? pathGroup;
String? internalPath;
String? nestedPath;
paths.keys.forEach((iterationPathGroup) {
var match = iterationPathGroup.pattern.firstMatch(path);
if (match != null) {
// longest matched path takes precidence
if (iterationPathGroup.length > (pathGroup?.length ?? -1)) {
var iterationRemainingPath = match.input.substring(match.end);
pathGroup = iterationPathGroup;
internalPath = match.group(0);
// nestedPath location must start with '/'
if (iterationRemainingPath.isNotEmpty &&
iterationRemainingPath[0] != '/') {
iterationRemainingPath = '/' + iterationRemainingPath;
}
// when no remaining path, nested navigator sets neseted path during build
nestedPath = iterationRemainingPath.isEmpty && query.isEmpty
? null
: iterationRemainingPath + '?' + query;
}
}
});
// update router config if match found
if (pathGroup != null) {
// parse args
var pathArgs = <String, String>{};
pathArgs.addAll(uri.queryParameters);
pathArgs.addAll(pathGroup!.args
.map((pos, argName) => MapEntry(argName, uri.pathSegments[pos])));
var args =
PathArguments(path: pathArgs, arguments: configuration.arguments);
changedPages = paths[pathGroup]?.call(args);
currentInternalPath = AdvancedRouteInformation(
location: internalPath,
state: configuration.state,
arguments: configuration.arguments,
);
currentNestedPath = nestedPath == null
? null
: AdvancedRouteInformation(
location: nestedPath, arguments: configuration.arguments);
}
}
// generate path with callback
if (changedPages == null) {
assert(() {
if (onGeneratePath == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'AdvancedNavigator.onGeneratePath was null but the referenced path had no corresponding path in the app.'),
ErrorDescription(
'The referenced path was: "${configuration.location}" '
'To use the AdvancedNavigator API with named paths (openNamed), '
'the AdvancedNavigator must be provided with either a matching reference '
'in the paths map or an onGeneratePath handler.\n'),
DiagnosticsProperty<String>('The AdvancedNavigator tag was', tag,
style: DiagnosticsTreeStyle.errorProperty),
DiagnosticsProperty<RouterDelegate>('The RouterDelegate was', this,
style: DiagnosticsTreeStyle.errorProperty),
]);
}
return true;
}());
var routerConfiguration = onGeneratePath!.call(configuration);
changedPages = routerConfiguration?.pages;
currentInternalPath = routerConfiguration?.internalPath;
currentNestedPath = routerConfiguration?.nestedPath;
if (changedPages == null) {
assert(() {
if (onUnknownPath == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'AdvancedNavigator.onGeneratePath returned null when requested to build path "${configuration.location}".'),
ErrorDescription(
'The onGeneratePath callback must never return null, unless an onUnknownPath '
'callback is provided as well.'),
DiagnosticsProperty<String>('The AdvancedNavigator tag was', tag,
style: DiagnosticsTreeStyle.errorProperty),
DiagnosticsProperty<RouterDelegate>(
'The RouterDelegate was', this,
style: DiagnosticsTreeStyle.errorProperty),
]);
}
return true;
}());
routerConfiguration = onUnknownPath!.call(configuration);
changedPages = routerConfiguration?.pages;
currentInternalPath = routerConfiguration?.internalPath;
currentNestedPath = routerConfiguration?.nestedPath;
assert(() {
if (changedPages == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'Navigator.onUnknownPath returned null when requested to build path "${configuration.location}".'),
ErrorDescription(
'The onUnknownPath callback must never return null.'),
DiagnosticsProperty<String>('The AdvancedNavigator tag was', tag,
style: DiagnosticsTreeStyle.errorProperty),
DiagnosticsProperty<RouterDelegate>(
'The RouterDelegate was', this,
style: DiagnosticsTreeStyle.errorProperty),
]);
}
return true;
}());
}
}
assert(changedPages != null);
_currentNestedPath = currentNestedPath;
_currentInternalPath = currentInternalPath ?? configuration;
_pages = List.unmodifiable(changedPages!);
onNestedPathUpdate(_currentNestedPath);
notifyListeners();
return SynchronousFuture(null);
}