Navigation Error with GetX State Management:

Issue

I can navigate first two screen (HomeMovie, HomeTvSeries) with Get.rootDelegate.toNamed method. But when I try to navigate to Detail Page from either of them, I am getting an error. I have followed the docs and examples but I couldn’t find anything. Any idea what are the reason that I am getting this?

This works:

onPressed: () {
  Get.rootDelegate.toNamed(AppRoutes.HOME_MOVIE);
},

This doesn’t:

onTap: () {
  Get.rootDelegate.toNamed(AppRoutes.DETAIL_MOVIE);
},

main.dart:

import 'package:device_preview/device_preview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

import '../../routes/index.dart';
import '../../util/index.dart';

Future<void> initServices() async {
  debugPrint('Starting GetX Services...');
  await GetStorage.init();
  await Get.putAsync(() => GlobalVariablesService().init());
  debugPrint('All GetX Services Started...');
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initServices();

  runApp(
    DevicePreview(
      enabled: false,
      builder: (BuildContext context) => const MovieApp(),
    ),
  );
}

class MovieApp extends StatelessWidget {
  const MovieApp({
    Key? key,
  }) : super(key: key);

  static GlobalKey movieAppKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp.router(
      key: movieAppKey,
      debugShowCheckedModeBanner: false,
      title: 'Flutter The Movie DB',
      translations: GetTranslations(),
      locale: Get.deviceLocale,
      fallbackLocale: GetTranslations.fallbackLocale,
      theme: Style.lightTheme,
      darkTheme: Style.darkTheme,
      themeMode: ThemeMode.system,
      defaultTransition: Transition.cupertino,
      getPages: AppPages.routes,
      enableLog: true,
      //logWriterCallback: (String text, {bool isError = false}) {}
      navigatorObservers: <NavigatorObserver>[
        GetObserver(),
      ],
    );
  }
}

AppPages.dart:

import 'package:get/get.dart';

import '../../bindings/index.dart';
import '../../routes/index.dart';
import '../../ui/screens/index.dart';

class AppPages {
  static final List<GetPage<dynamic>> routes = <GetPage<dynamic>>[
    GetPage<dynamic>(
      name: AppRoutes.START,
      page: () => const StartScreen(),
      binding: StartBinding(),
      preventDuplicates: true,
      children: <GetPage<dynamic>>[
        GetPage<dynamic>(
          name: AppRoutes.HOME_MOVIE,
          page: () => const HomeMovieScreen(),
          transition: Transition.cupertino,
          binding: HomeMovieBinding(),
          children: <GetPage<dynamic>>[
            GetPage<dynamic>(
              name: AppRoutes.DETAIL_MOVIE,
              page: () => const DetailPage(),
              transition: Transition.cupertino,
              binding: DetailPageBinding(),
            ),
          ],
        ),
        GetPage<dynamic>(
          name: AppRoutes.HOME_TV,
          page: () => const HomeTvScreen(),
          transition: Transition.cupertino,
          binding: HomeTvBinding(),
          children: <GetPage<dynamic>>[
            GetPage<dynamic>(
              name: AppRoutes.DETAIL_TV,
              page: () => const DetailPage(),
              transition: Transition.cupertino,
              binding: DetailPageBinding(),
            ),
          ],
        ),
      ],
    ),
  ];
}

This is the error.

Error:

 ======== Exception caught by widgets library =======================================================
    The following assertion was thrown building Builder:
    'package:flutter/src/widgets/navigator.dart': Failed assertion: line 3619 pos 18: '!keyReservation.contains(key)': is not true.
    
    
    Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
    In either case, please report this assertion by filing a bug on GitHub:
      https://github.com/flutter/flutter/issues/new?template=2_bug.md
    
    The relevant error-causing widget was: 
      GetMaterialApp-[GlobalKey#5e03f] file:///C:/Users/hazar/AndroidStudioProjects/flutter_getx_the_moviedb/lib/main.dart:38:27
    When the exception was thrown, this was the stack: 
    #2      NavigatorState._debugCheckDuplicatedPageKeys.<anonymous closure> (package:flutter/src/widgets/navigator.dart:3619:18)
    #3      NavigatorState._debugCheckDuplicatedPageKeys (package:flutter/src/widgets/navigator.dart:3624:6)
    #4      NavigatorState._updatePages.<anonymous closure> (package:flutter/src/widgets/navigator.dart:3659:7)
    #5      NavigatorState._updatePages (package:flutter/src/widgets/navigator.dart:3662:6)
    #6      NavigatorState.didUpdateWidget (package:flutter/src/widgets/navigator.dart:3606:7)

Solution

I figured it out. The problem was GetMaterialApp.router. When you choose to use this type of MaterialApp, you have to create GetDelegate manually. That’s because, I could use Get.rootDelegate.toNamed() method. But I think this way is more expensive and more complex. So, I had to change 3 different things to make it work:

1- Change GetMaterialApp.router => GetMaterialApp. Then add initialRoute.

main.dart:

import 'package:device_preview/device_preview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';

import '../../routes/index.dart';
import '../../util/index.dart';

Future<void> initServices() async {
  debugPrint('Starting GetX Services...');
  await GetStorage.init();
  await Get.putAsync(() => GlobalVariablesService().init());
  debugPrint('All GetX Services Started...');
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initServices();

  runApp(
    DevicePreview(
      enabled: false,
      builder: (BuildContext context) => const MovieApp(),
    ),
  );
}

class MovieApp extends StatelessWidget {
  const MovieApp({
    Key? key,
  }) : super(key: key);

  static GlobalKey movieAppKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      key: movieAppKey,
      debugShowCheckedModeBanner: false,
      title: 'Flutter The Movie DB',
      translations: GetTranslations(),
      locale: Get.deviceLocale,
      fallbackLocale: GetTranslations.fallbackLocale,
      theme: Style.lightTheme,
      darkTheme: Style.darkTheme,
      themeMode: ThemeMode.system,
      defaultTransition: Transition.cupertino,
      getPages: AppPages.routes,
      initialRoute: AppRoutes.START,
      enableLog: true,
      //logWriterCallback: (String text, {bool isError = false}) {}
      navigatorObservers: <NavigatorObserver>[
        GetObserver(),
      ],
    );
  }
}

2- Change AppPages.routes to this:

app_pages.dart:

import 'package:get/get.dart';

import '../../bindings/index.dart';
import '../../routes/index.dart';
import '../../ui/screens/index.dart';

class AppPages {
  static final List<GetPage<dynamic>> routes = <GetPage<dynamic>>[
    GetPage<StartScreen>(
      name: AppRoutes.START,
      page: () => const StartScreen(),
      binding: StartBinding(),
      preventDuplicates: true,
    ),
    GetPage<HomeMovieScreen>(
      name: AppRoutes.HOME_MOVIE,
      page: () => const HomeMovieScreen(),
      transition: Transition.cupertino,
      binding: HomeMovieBinding(),
    ),
    GetPage<HomeTvScreen>(
      name: AppRoutes.HOME_TV,
      page: () => const HomeTvScreen(),
      transition: Transition.cupertino,
      binding: HomeTvBinding(),
    ),
    GetPage<DetailPage>(
      name: AppRoutes.DETAIL,
      page: () => const DetailPage(),
      transition: Transition.cupertino,
      binding: DetailPageBinding(),
    ),
  ];
}

3- And finally, change Get.rootDelegate.toNamed() => Get.toNamed()

Now, this works! :

Get.toNamed(
  AppRoutes.DETAIL,
  arguments: <String, dynamic>{
    'movie': movieWrapper.results?[index],
    'isMovie': true,
  },
);

Answered By – Hazar Belge

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

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