Could not navigate to initial route error when changing browser Url Flutter

Issue

I’m updating my code to use Navigator 2.0 and dough the navigation through NavigationBar‘s buttons works properly switching pages and updating the browser Url accordingly when I change it manually it throws an error:

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.

Also back buttons is not working, and throws the Duplicate GlobalKey detected in widget tree.error.
Can the problem be that I check for routeInformation.location in my Parser?

edit

I tried putting the switch inside the uri.pathSegment.lenght check checking on uri.pathSegments.first and the back button now works dough still throwing the Duplicate GlobalKey detected in widget tree.error.

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) {
...

This is my Parser:

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');
    }
  }
}

I also noticed through the prints I set that there might be a weird loop when the app first loads:

Parser

  1. AppRouteInformationParser.parseRouteInformation called for /
  2. AppRouteInformationParser uri has no segments and is /
  3. AppRouteInformationParser.urlSegment switch case : /

RuterDelegate

  1. RouterDelegate.currentConfiguration appState.selectedPage is

Parser

  1. AppRouteInformationParser.restoreRouteInformation called for path /
  2. restoreRouteInformation RouteInformation.location: /

RouterDelegate

  1. RouterDelegate.setNewRoutePath path is /

AppState

  1. AppState setting selectedPage to /
    which triggers delegate build, so again

RouterDelegate

  1. RouterDelegate.currentConfiguration appState.selectedPage is /

Parser

  1. AppRouteInformationParser.restoreRouteInformation called for path /
  2. restoreRouteInformation RouteInformation.location: /

Non expected prints

RouterDelegate

  1. RouterDelegate.currentConfiguration appState.selectedPage is /

Parser

  1. AppRouteInformationParser.restoreRouteInformation called for path /
  2. restoreRouteInformation RouteInformation.location: /

As when a button is pressesed then I only get :

Button

1.selected tapped is /about

AppState

  1. AppState setting selectedPage to /about

RouterDelegate

  1. RouterDelegate.currentConfiguration appState.selectedPage is /about

Parser

  1. AppRouteInformationParser.restoreRouteInformation called for path /about
  2. restoreRouteInformation RouteInformation.location: /about

Solution

After a couple of days of struggling I finally found the problem:

In main.dart build method I was returning a MaterialApp with a MaterialApp.router as its home: instead that returning a MaterialApp.router directly and move all the MaterialApp configuration parameters into it.
Everything works just as expected now.

wrong way :

  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),
    );
  }

correct way is :

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: ,
    );
  }

Answered By – Vincenzo

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *