更改浏览器 Url Flutter 时无法导航到初始路由错误
Posted
技术标签:
【中文标题】更改浏览器 Url Flutter 时无法导航到初始路由错误【英文标题】:Could not navigate to initial route error when changing browser Url Flutter 【发布时间】:2022-01-04 09:43:02 【问题描述】:我正在更新我的代码以使用 Navigator 2.0,并且通过 NavigationBar
的按钮进行导航可以正常切换页面并相应地更新浏览器 URL,当我手动更改它时会引发错误:
Could not navigate to initial route.
The requested route name was: "/retailers"
There was no corresponding route in the app, and therefore the initial route specified will be ignored and "/" will be used instead.
后退按钮也不起作用,并引发Duplicate GlobalKey detected in widget tree.
error。
问题是我在解析器中检查routeInformation.location
吗?
编辑
我尝试将开关放在uri.pathSegment.lenght
中检查uri.pathSegments.first
,现在后退按钮可以正常工作,但仍然抛出Duplicate GlobalKey detected in widget tree.
错误。
if (uri.pathSegments.length > 0)
print(
'Uri.segments.first is: $uri.pathSegments.first..uri.path is: $uri.path');
// switch (routeInformation.location)
switch (uri.pathSegments.first)
...
这是我的解析器:
class AppRouteInformationParser extends RouteInformationParser<RoutePath>
@override
Future<RoutePath> parseRouteInformation(
RouteInformation routeInformation) async
print(
'AppRouteInformationParser.parseRouteInformation called for $routeInformation.location');
final Uri uri = Uri.parse(routeInformation.location);
if (uri.pathSegments.length > 0)
print(
'Uri.segments.first is: $uri.pathSegments.first, uri.path is: $uri.path');
else
print('AppRouteInformationParser uri has no segments and is $uri');
switch (routeInformation.location)
// switch (uri.pathSegments.first)
case '/':
print('AppRouteInformationParser.urlSegment switch case : /');
// return CyclistsPath();
return HomePath();
case CyclistsLandingRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /cyclists');
return CyclistsPath();
case '/retailers':
print(
'AppRouteInformationParser.routeInformation.location switch case: /retailers');
return RetailersPath();
case '/map':
print(
'AppRouteInformationParser.routeInformation.location switch case: /map');
return MapPath();
case AboutRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /about');
return AboutPath();
case TermsOfServiceRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /terms-of-service');
return TermsOfServicePath();
case PrivacyPolicyRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /privacy-policy');
return PrivacyPolicyPath();
case PrivacySettingsRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /privacy-settings');
return PrivacySettingsPath();
case CommunityGuidelinesRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /community-guidelines');
return CommunityGuidelinesPath();
case LegalNoticeRoute:
print(
'AppRouteInformationParser.routeInformation.location switch case: /legal-notice');
return LegalPath();
default:
print(
'### default AppRouteInformationParser.routeInformation.location switch case ## default: /');
return HomePath();
@override
RouteInformation restoreRouteInformation(RoutePath path)
print(
'AppRouteInformationParser.restoreRouteInformation called for path $path.selectedPath');
switch (path.selectedPath)
case '/':
// case CyclistsLandingRoute:
print('restoreRouteInformation RouteInformation.location: /');
return RouteInformation(location: '/');
case '/cyclists':
// case CyclistsLandingRoute:
print('restoreRouteInformation RouteInformation.location: /cyclists');
return RouteInformation(location: '/cyclists');
case '/retailers':
print('restoreRouteInformation RouteInformation.location: /retailers');
return RouteInformation(location: '/retailers');
case '/map':
print('restoreRouteInformation RouteInformation.location: /map');
return RouteInformation(location: '/map');
case '/about':
print('restoreRouteInformation RouteInformation.location: /about');
return RouteInformation(location: '/about');
case '/terms-of-service':
print(
'restoreRouteInformation RouteInformation.location: /terms-of-service');
return RouteInformation(location: '/terms-of-service');
case '/privacy-policy':
print(
'restoreRouteInformation RouteInformation.location: /privacy-policy');
return RouteInformation(location: '/privacy-policy');
case '/privacy-settings':
print(
'restoreRouteInformation RouteInformation.location: /privacy-settings');
return RouteInformation(location: '/privacy-settings');
case '/community-guidelines':
print(
'restoreRouteInformation RouteInformation.location: /community-guidelines');
return RouteInformation(location: '/community-guidelines');
case '/legal-notice':
print(
'restoreRouteInformation RouteInformation.location: /legal-notice');
return RouteInformation(location: '/legal-notice');
default:
print(
'restoreRouteInformation ### Default RouteInformation.location: /cyclists');
return RouteInformation(location: '/cyclists');
通过我设置的打印我还注意到,当应用第一次加载时可能会有一个奇怪的循环:
解析器
AppRouteInformationParser.parseRouteInformation called for /
AppRouteInformationParser uri has no segments and is /
AppRouteInformationParser.urlSegment switch case : /
RuterDelegate
RouterDelegate.currentConfiguration appState.selectedPage is
解析器
AppRouteInformationParser.restoreRouteInformation called for path /
restoreRouteInformation RouteInformation.location: /
路由器代理
RouterDelegate.setNewRoutePath path is /
应用状态
AppState setting selectedPage to /
这会触发委托构建,所以再次
路由器代理
RouterDelegate.currentConfiguration appState.selectedPage is /
解析器
AppRouteInformationParser.restoreRouteInformation called for path /
restoreRouteInformation RouteInformation.location: /
非预期打印
路由器代理
RouterDelegate.currentConfiguration appState.selectedPage is /
解析器
AppRouteInformationParser.restoreRouteInformation called for path /
restoreRouteInformation RouteInformation.location: /
当按下按钮时,我只会得到:
按钮
1.selected tapped is /about
应用状态
AppState setting selectedPage to /about
路由器代理
RouterDelegate.currentConfiguration appState.selectedPage is /about
解析器
AppRouteInformationParser.restoreRouteInformation called for path /about
restoreRouteInformation RouteInformation.location: /about
【问题讨论】:
【参考方案1】:经过几天的努力,我终于找到了问题:
在 main.dart 构建方法中,我返回了 MaterialApp
和 MaterialApp.router
作为其 home:
,而不是直接返回 MaterialApp.router
并将所有 MaterialApp
配置参数移入其中。
现在一切正常。
错误的方式:
AppRouterDelegate _routerDelegate = AppRouterDelegate();
AppRouteInformationParser _routeInformationParser =
AppRouteInformationParser();
@override
Widget build(BuildContext context)
return MaterialApp(
title: '',
color: Colors.red,
localizationsDelegates: [
const AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'),
const Locale('it', 'IT')
// const Locale('es', 'ES'),
],
localeResolutionCallback:
(Locale locale, Iterable<Locale> supportedLocales)
for (Locale supportedLocale in supportedLocales)
if (supportedLocale.languageCode == locale.languageCode ||
supportedLocale.countryCode == locale.countryCode)
print('Web device Locale is $locale');
return supportedLocale;
return supportedLocales.first;
,
debugShowCheckedModeBanner: false,
home: MaterialApp.router(
routeInformationParser: _routeInformationParser,
routerDelegate: _routerDelegate),
);
正确的方法是:
AppRouterDelegate _routerDelegate = AppRouterDelegate();
AppRouteInformationParser _routeInformationParser =
AppRouteInformationParser();
@override
Widget build(BuildContext context)
return MaterialApp.router(
routeInformationParser: _routeInformationParser,
routerDelegate: _routerDelegate,
debugShowCheckedModeBanner: false,
title: '',
color: Colors.red,
localizationsDelegates: [
const AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'),
const Locale('it', 'IT')
// const Locale('es', 'ES'),
],
localeResolutionCallback:
(Locale locale, Iterable<Locale> supportedLocales)
for (Locale supportedLocale in supportedLocales)
// if (UniversalPlatform.isWeb)
if (supportedLocale.languageCode == locale.languageCode ||
supportedLocale.countryCode == locale.countryCode)
print('Web device Locale is $locale');
return supportedLocale;
return supportedLocales.first;
,
// localeListResolutionCallback: ,
);
【讨论】:
以上是关于更改浏览器 Url Flutter 时无法导航到初始路由错误的主要内容,如果未能解决你的问题,请参考以下文章