简体   繁体   English

在 Flutter 中,Getx 包 unknownRoute 不起作用

[英]In Flutter, Getx package unknownRoute not working

I'm starting to learn Getx in flutter, and using navigation.我开始在颤振中学习 Getx,并使用导航。

I want to set unknownRoute, in case that there is a typo etc in the namedroute, so the app should go to a default page.我想设置unknownRoute,以防namedroute中有错字等,因此应用程序应该转到默认页面。

I do like this:我喜欢这样:

 return GetMaterialApp(
        title: 'Named navigation',
        unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
        initialRoute: '/', // this defines with route will be opened first

        getPages: [
          GetPage(name: '/', page: () => MyNavigationNamed()),
          GetPage(name: '/second', page: () => SecondScreenNamed()),
          GetPage(name: '/third', page: () => ThirdParametersScreenNamed()),
          GetPage(
              name: '/third_with_built_param/:someValue',
              page: () => ThirdParametersScreenNamed()),
        ],

I have the widget:我有小部件:

class UnknownRoutePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(child: Text('UNKNOWN ROUTE')));
  }

}

However, then when I try to test it by making a mistake in the route name, like this:但是,当我尝试通过在路由名称中出错来测试它时,如下所示:

 ElevatedButton(
                  onPressed: () {
                    Get.toNamed(
                      '/s');     //THIS IS A DUMMY INCORRECT NAME TO TESTING
                  },
                  child: Text('Error in route name, goes to defalt set above.'),
                ),

I expect my UnknownRoutePage() to open.我希望我的 UnknownRoutePage() 能够打开。

However I get this message:但是我收到此消息:

The following assertion was thrown building Directionality(textDirection: ltr):
'package:flutter/src/widgets/framework.dart': Failed assertion: line 5033 pos 14: '_dependents.isEmpty': 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: 
  Directionality file:///Users/reuvenberman/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/get-4.3.8/lib/get_navigation/src/root/get_material_app.dart:217:12
When the exception was thrown, this was the stack: 
#2      InheritedElement.debugDeactivated.<anonymous closure> (package:flutter/src/widgets/framework.dart:5033:14)
#3      InheritedElement.debugDeactivated (package:flutter/src/widgets/framework.dart:5035:6)
#4      _InactiveElements._deactivateRecursively.<anonymous closure> (package:flutter/src/widgets/framework.dart:1869:15)
#5      _InactiveElements._deactivateRecursively (package:flutter/src/widgets/framework.dart:1871:6)
#6      ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:4628:14)
...
====================================================================================================

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.

The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of the widget tree being truncated unexpectedly, because the second time a key is seen, the previous instance is moved to the new location. The key was:
- [LabeledGlobalKey<NavigatorState>#56deb Key Created by default]
This was determined by noticing that after the widget with the above global key was moved out of its previous parent, that previous parent never updated during this frame, meaning that it either did not update at all or updated before the widget was moved, in either case implying that it still thinks that it should have a child with that global key.
The specific parent that did not update after having one or more children forcibly removed due to GlobalKey reparenting is:
- Directionality(textDirection: ltr)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack: 
#0      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2900:15)
#1      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2925:8)
#2      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:877:19)
#3      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:328:5)
#4      SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
...

Why isn't this working?为什么这不起作用?

Thanks谢谢

I am facing the same problem and also could not find any information surrounding the subject.我面临同样的问题,也找不到有关该主题的任何信息。 after doing some testing and reviewing the actual package code I came to the conclusion that GetX only cares if it can match the route at the start of the URI.在做了一些测试并查看了实际的包代码之后,我得出的结论是 GetX 只关心它是否可以匹配 URI 开头的路由。 So if you have a route for "/" then anything after the "/" such as "/non-existent-route/1/2/3/" will still match "/" because it starts with "/".因此,如果您有“/”的路由,那么“/”之后的任何内容(例如“/non-existent-route/1/2/3/”)仍将匹配“/”,因为它以“/”开头。 Similarly, if you have a route like "/admin-area" and another for "/admin-area/home" then "/admin-area/non-existent-route/1/2/3/" would still get matched with "/admin-area" and a URI like "/admin-area/home/non-existent-route/1/2/3/" would still match with "/admin-area/home".同样,如果你有一个像“/admin-area”这样的路由,另一个是“/admin-area/home”,那么“/admin-area/non-existent-route/1/2/3/”仍然会匹配到"/admin-area" 和类似 "/admin-area/home/non-existent-route/1/2/3/" 的 URI 仍将与 "/admin-area/home" 匹配。 As this is not the expected behaviour for the web, it can cause problems when using the currentRoute to highlight the current page in your navigation, and considering the documentation for GetX is so poor, I can only assume this is a bug.由于这不是 web 的预期行为,当使用 currentRoute 在导航中突出显示当前页面时可能会导致问题,并且考虑到 GetX 的文档非常差,我只能假设这是一个错误。

The only way I could properly get around this issue is by not using the GetMaterialApp getPages property at all and using onGenerateRoute instead.我可以正确解决此问题的唯一方法是根本不使用 GetMaterialApp getPages 属性,而是使用 onGenerateRoute 。 Get.toNamed still works and the router will only route to exact matches, like this: Get.toNamed 仍然有效,路由器只会路由到完全匹配,如下所示:

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      initialRoute: "/",
      onGenerateRoute: (RouteSettings route) {
        var uri = Uri.parse(route.name!);
        switch (uri.path) {
          case "/":
            return MaterialPageRoute(
              settings: route,
              builder: (context) => const RootPage(),
            );
          default:
            return MaterialPageRoute(
              settings: route,
              builder: (context) => const UnkownPage(),
            );
        }
      },
    );
  }

if you wish, you can also move this logic out of the GetMaterialApp like this:如果您愿意,您还可以像这样将此逻辑移出 GetMaterialApp:

@override
Widget build(BuildContext context) {
  return GetMaterialApp(
    initialRoute: "/",
    onGenerateRoute: generateRoutes
    },
  );
}

//another file
Route<dynamic> generateRoutes(RouteSettings route) {
  var uri = Uri.parse(route.name!);
  switch (uri.path) {
    case "/":
      return MaterialPageRoute(
        settings: route,
        builder: (context) => const UnimplementedPage('Unkown'),
      );
    default:
      return MaterialPageRoute(
        settings: route,
        builder: (context) => const UnimplementedPage('Unkown'),
      );
  }
}

I had the same issue, but I dig into the Get code, and found out there is a matchRoute() method will return "/" for unknownRoute.我遇到了同样的问题,但我深入研究了 Get 代码,发现有一个matchRoute()方法将为 unknownRoute 返回“/”。

--> In short, to make the unknownRoute work, your initial route could not be "/", it can be anything else, such as "/home", "/main", "/init", but it just can't be "/". --> 总之,要让unknownRoute工作,你的初始路由不能是“/”,它可以是其他任何东西,例如“/home”、“/main”、“/init”,但它只是可以' t 是“/”。


I created a PR for it : https://github.com/jonataslaw/getx/pull/2256我为它创建了一个 PR: https ://github.com/jonataslaw/getx/pull/2256

I faced a similar problem, but I didn't receive any error messages.我遇到了类似的问题,但没有收到任何错误消息。 Instead, when I tried to navigate to a non-existent page, I always ended up on the start page.相反,当我试图导航到一个不存在的页面时,我总是在起始页面上结束。 I have not found any clarification on this.我没有找到任何澄清。

My solution was to set something more weighty for initialRoute, for example: initialRoute: '/beginpage'.我的解决方案是为 initialRoute 设置更重要的内容,例如:initialRoute: '/beginpage'。 '/' and '/start' did not work for me, maybe they are some reserved routes. '/' 和 '/start' 对我不起作用,也许它们是一些保留路线。 I see the same problem in your code, try changing it as well.我在您的代码中看到了同样的问题,请尝试更改它。

If this does not help, you can look at a ready-made example that I found on github and which helped me identify my problem: https://github.com/ducafecat/getx_quick_start .如果这没有帮助,您可以查看我在 github 上找到的现成示例,它帮助我确定了我的问题: https ://github.com/ducafecat/getx_quick_start。

I found a simple way that you can skip the main page in "getPage:" because of "initialRoute:" implemented.我找到了一种简单的方法,您可以跳过“getPage:”中的主页,因为实现了“initialRoute:”。

return GetMaterialApp(
    title: 'Named navigation',
    unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),
    initialRoute: '/',

    getPages: [

      GetPage(name: '/second', page: () => SecondScreenNamed()),
      GetPage(name: '/third', page: () => ThirdParametersScreenNamed()),
      GetPage(
          name: '/third_with_built_param/:someValue',
          page: () => ThirdParametersScreenNamed()),
    ],

Try it.试试看。

I solved我解决了

notWorking UnknownRoute notWorking 未知路由

First AppInformationParser put inside GetMaterialApp.router第一个AppInformationParser放入GetMaterialApp.router

routeInformationParser: AppInformationParser()

   return GetMaterialApp.router(
      title: 'ACRI',
      debugShowCheckedModeBanner: false,
      theme: AppTheme.appTheme,
      themeMode: ThemeMode.light,
      locale: Get.locale ?? const Locale('tr'),
      translations: AppLocalization(),
      routerDelegate: Get.createDelegate(
        backButtonPopMode: PopMode.Page,
        notFoundRoute: AppPages.pageNotFound,
      ),
      localizationsDelegates: AppLocalizationDelegate.appDelegates,
      supportedLocales: AppLocalizationDelegate.supportedLocales,
      routeInformationParser: AppInformationParser(),
      backButtonDispatcher: AppBackButtonDispatcher(),
      getPages: AppPages.pages,
      initialBinding: AccountBinding(),
      unknownRoute: AppPages.pageNotFound,
    );

and create AppInformationParser class并创建AppInformationParser

  class AppInformationParser extends RouteInformationParser<GetNavConfig> {
  /// [initialRoute] => [/]
  AppInformationParser({
    String? initialRoute,
  })  : initialRoute = initialRoute ?? '/',
        super();

  /// Initial route
  /// default '/'
  final String initialRoute;

  @override
  Future<GetNavConfig> parseRouteInformation(
    RouteInformation routeInformation,
  ) {
    String? location = routeInformation.location; // => [/]
    if (location == '/') {
      if (!Get.routeTree.routes.any((e) => e.name == '/')) {
        location = initialRoute;
      }
    }

    // if (!Get.routeTree.routes.any((e) => false)) {
    //   location = AppRoutes.notFound;
    // }

    final matchResult = Get.routeTree.matchRoute(location ?? initialRoute);
    String? matchResultLocation = matchResult.route?.name;

    log("App Information Parser location : $location");
    log("Match Result Parser location : ${matchResult.route?.name}");

    if (matchResultLocation != location) {
      location = AppRoutes.notFound;
    } else if (matchResultLocation == AppRoutes.navigation) {
      location = AppRoutes.home;
    } else if (matchResultLocation == AppRoutes.list) {
      location = AppRoutes.vehicles;
    } else if (matchResultLocation == AppRoutes.report) {
      location = AppRoutes.vehicleReport;
    } else if (matchResultLocation == AppRoutes.map) {
      location = AppRoutes.mapVehicles;
    }

    final result = Get.routeTree.matchRoute(location ?? initialRoute);

    return SynchronousFuture(
      GetNavConfig(
        currentTreeBranch: result.treeBranch,
        location: location,
        state: routeInformation.state,
      ),
    );
  }

  @override
  RouteInformation? restoreRouteInformation(GetNavConfig configuration) {
    return RouteInformation(
      location: configuration.location,
      state: configuration.state,
    );
  }
}

This gives to you entred router name这会给你输入的路由器名称

 final matchResult = Get.routeTree.matchRoute(location ?? initialRoute);
 String? matchResultLocation = matchResult.route?.name;

and compare your location router并比较您的location路由器

   if (matchResultLocation != location) {
      location = AppRoutes.notFound;
    }

if matchResultLocation not compare location so it is unknown router.如果matchResultLocation不比较location ,则它是未知路由器。

And finally matchRoute methods added again for GetNavConfig and solved UnknownRoute最后为GetNavConfig添加了matchRoute方法并解决UnknownRoute

    final result = Get.routeTree.matchRoute(location ?? initialRoute);

    return SynchronousFuture(
      GetNavConfig(
        currentTreeBranch: result.treeBranch,
        location: location,
        state: routeInformation.state,
      ),
    );

Solved: First i used getPages property from GetMaterialApp :已解决:首先我使用了 GetMaterialApp 中的 getPages 属性:

    return GetMaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      debugShowCheckedModeBanner: false,
      title: Constants.appName,
      //Rutas fluro
      // onGenerateRoute: Flurorouter.router.generator,
      // onGenerateRoute: (RouteSettings route){
      //   var uri = Uri.parse(route.name!);
      //   switch (uri.path) {
      //     case "/":
      //       return GetMaterialPageView(
      //         settings: route,
      //         builder: (context) => const RootPage(),
      //       );
      //     default:
      //       return MaterialPageRoute(
      //         settings: route,
      //         builder: (context) => const UnkownPage(),
      //       );
      //   }  
      // },
      initialBinding: InitialBindings(),
      initialRoute: AppRoutes.initialRoute,
      getPages: AppPages.pages,
      unknownRoute: GetPage(name: '/notfound', page: () => const Screen404()),
      // routes: AppRoutes.getAppRoutes(),
      theme: AppTheme.lightTheme,
    );

Inside of AppPages.Pages i have all the pages of my project, each page looks like this:在 AppPages.Pages 里面我有我项目的所有页面,每个页面看起来像这样:

    GetPage(
      name: AppRoutes.SPLASH,
      page: () => AppRoutes.routes.contains(Get.currentRoute)
        ?SplashScreen()
        :const Screen404(),
    ),

before return a page i use this validation on page property to return the current route and validate if the route is the same what i defined on AppRoutes if isn't the same i return an Screen 404.在返回页面之前,我在页面属性上使用此验证来返回当前路由并验证路由是否与我在 AppRoutes 上定义的相同,如果不一样,我会返回屏幕 404。

In case the route has parameters like this:如果路由有这样的参数:

    GetPage(  
      name: "${AppRoutes.CANCEL_RESERVATION}/:id_reservation",
      page: (){
        //TODO VERIFICAR QUE ID EXISTA EN LISTADO DE AMENIDADES
        print(Get.parameters);
        print(Get.currentRoute);
        final id = int.tryParse(Get.parameters['id_reservation']!);
        final controller = Get.find<MyReservationsController>();
        controller.getReservationSelectedToCancel(id);
        if(controller.myReservationToCanel != null){
          return CancelReservationScreen(
            reservation: id,
          ); 
        }else{
          return const Screen404();
        }
      },
      binding: MyReservationsBinding(),
    ),

On this way we can use bindings too.这样我们也可以使用绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 自定义小部件无法按预期工作 - GetX package Flutter - Custom widget not working as expected - GetX package Flutter flutter getx 包不工作,显示错误 - flutter getx package not working, showing error 带有 PATCH 方法的 GetX 不起作用(Flutter) - GetX with PATCH method not working (Flutter) GetMidleware 在底部导航栏上不起作用 - flutter - GetX - GetMidleware not working on bottomNavigationBar - flutter - GetX 为什么在颤动中点击通知时路由不起作用? (项目基于GetX和flutter本地推送通知包) - why routing is not working when tap on the notification in flutter? ( the project is based on GetX and flutter local push notification package ) 在 flutter 中使用 GetX package 的导航问题 - Navigation problem using GetX package in flutter 使用 FirebaseAuth 的 GetX(更新到 4.1.1) - Flutter 身份验证不起作用 - GetX (updated to 4.1.1) with FirebaseAuth - Flutter authentication not working Flutter - 使用 GetX 的页面替换系统不工作 - Flutter - Page replacement system with GetX not working 在我的场景中,哪个包更好 flutter_secure_storage 或 getx ? - Which package is better flutter_secure_storage or getx in my scenario? 如何使用 GetX 包管理 Flutter Web URL 路由? - How to manage Flutter web URL routes using the GetX package?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM