命名路线导航错误:类型'MaterialPageRoute <dynamic>'不是类型'Route <String>'的子类型

Mic*_*ies 3 flutter

我正在尝试使用命名路线导航到另一个页面:

... RaisedButton(
            child: Text('Get image'),
            onPressed: () => Navigator.pushNamed<String>(
                context, '/second'),...
Run Code Online (Sandbox Code Playgroud)

但是得到错误

> I/flutter (12439): ??? EXCEPTION CAUGHT BY GESTURE
> ????????????????????????????????????????????????????????????????????
>     I/flutter (12439): The following assertion was thrown while handling a gesture:
>     I/flutter (12439): type 'MaterialPageRoute<dynamic>' is not a subtype of type 'Route<String>'
>     I/flutter (12439): Either the assertion indicates an error in the framework itself, or we should provide substantially
>     I/flutter (12439): more information in this error message to help you determine and fix the underlying cause.
>     I/flutter (12439): In either case, please report this assertion by filing a bug on GitHub:
>     I/flutter (12439):   https://github.com/flutter/flutter/issues/new?template=BUG.md
>     I/flutter (12439): When the exception was thrown, this was the stack:
>     I/flutter (12439): #0      NavigatorState._routeNamed package:flutter/…/widgets/navigator.dart:1426
>     I/flutter (12439): #1      NavigatorState.pushNamed package:flutter/…/widgets/navigator.dart:1473
>     I/flutter (12439): #2      Navigator.pushNamed package:flutter/…/widgets/navigator.dart:740
>     I/flutter (12439): #3      _CompleterState.build.<anonymous closure> package:my_package/completer.dart:205
Run Code Online (Sandbox Code Playgroud)

该路线在首页中定义:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'XXXX',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Completer(),
      routes: {
        '/second': (BuildContext context) => SecondPage(),
      },
      onUnknownRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          builder: (BuildContext context) => Completer(),
        );
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我在此错误消息上找不到任何内容,因此似乎产生了一个以前没有人见过的错误。

我正在慢慢修改代码以将其简化到最低限度,以找出我做错了什么,但是任何指针将不胜感激。

liv*_*ove 12

改变这个:

     MyType result = await Navigator.pushNamed(
                context,
                MyPage.routeName,
                arguments: PageArguments(myArg);
Run Code Online (Sandbox Code Playgroud)

到:

     var result = await Navigator.pushNamed(
                context,
                MyPage.routeName,
                arguments: PageArguments(myArg);
Run Code Online (Sandbox Code Playgroud)


小智 10

发现这Navigator.pushNamed(context, '/second') as String与命名路由配合得很好,当从第二个命名页面返回数据并使用更严格的类型时(一切都应该如此),这将很有用


Tim*_*low 8

具有类型提示确实有意义,它有助于调试,并在类型不是您期望的类型时让 IDE 标记。(在可能的情况下强类型的忠实粉丝)

你可以用你命名的路线来做到这一点 - 万岁!

您已经使用 的routes属性实现了路由处理,MaterialApp但正如您发现的那样,没有任何地方可以添加您正在创建的路由的返回类型。

routes: {
  '/second': (BuildContext context) => SecondPage(),
}
Run Code Online (Sandbox Code Playgroud)

这意味着传递给它的任何实例都必须具有返回类型dynamic并为其他任何东西抛出错误。

生成路由

为了指定返回类型,需要多一点代码和使用 的onGenerateRoute属性MaterialApp

MaterialApp(
  // ... All the other properties
  // You can still have the simple 'routes' version at the same time
  // so don't need to implement all routes in long-form below
  routes: <String, WidgetBuilder>{
    '/first': (BuildContext context) => FirstPage();
  },
  onGenerateRoute: (RouteSettings settings) {
    final String routeName = settings.name;
    final Map<String, dynamic> args = settings.arguments;  // Get any arguments passed to the route

    switch (routeName) {
      case '/second':
        // Set the Route return value here to correspond with pushNamed<String> for example
        return MaterialPageRoute<String>(
            builder: (BuildContext context) => SecondPage(arg1: args["arg1"]);
            settings: settings,
        );
    }
)
Run Code Online (Sandbox Code Playgroud)

这现在将处理pushNamed<String>('/second')- 并且非常高兴!


Mic*_*ies 7

在事后看来非常明显。

我已经添加了String类型提示,Navigator.pushNamed<String>()因为我认为我可以从调用返回一个类型化的值。将其删除并将其接收到var中即可解决此问题。

将此留给其他任何处于同一状态的人。

  • @ruwan800 - 因为当您在定义所有路线时使用 `routes` 属性时,您隐式定义了 `MaterialPageRoute&lt;dynamic&gt;` 实例,该实例无法转换为类型化 Route 实例(如 `Route&lt;MyType&gt;`),因此您必须使用动态推送,例如“Navigator.pushNamed(...)”(不是“Navigator.pushNamed&lt;MyType&gt;(...)”),它隐式定义了“Navigator.pushNamed&lt;dynamic&gt;(...)” (12认同)
  • 欣赏它!替我回答了。 (2认同)
  • @SimonMourier,你应该将其添加为答案而不是评论,这非常有帮助,谢谢 (2认同)