【问题标题】:flutter return data from a screen error with pushNamed()使用 pushNamed() 从屏幕错误中颤振返回数据
【发布时间】:2019-04-04 06:15:00
【问题描述】:

我使用 pushNamed() 从屏幕获取返回数据,如下所示:

_pushToPage2() async {
    String result = await Navigator.pushNamed(context, "/page2");
    print("$tag $result");
}

但代码有问题,这是完整的错误堆栈跟踪:

E/flutter:[ERROR:flutter/shell/common/shell.cc(181)] Dart 错误:未处理的异常:
“MaterialPageRoute”类型不是“Route”类型的子类型
0 NavigatorState._routeNamed (package:flutter/src/widgets/navigator.dart:1408:14)
1 NavigatorState.pushNamed (package:flutter/src/widgets/navigator.dart:1454:20)
2 _MyHomePageState._pushToPage2 (file:///Users/wang/flutter_project/flutter_navigation/lib/main.dart:113:50)
3 _MyHomePageState.build。 (file:///Users/wang/flutter_project/flutter_navigation/lib/main.dart:58:19)
4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:507:14)
5 _InkResponseState.build。 (包:flutter/src/material/ink_well.dart:562:30)
6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
7 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
8 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:175:7)
9 PrimaryPointerGestureRecognizer.handleEvent(包:flutter/src/gestures/recognizer.dart:315:9)
10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
11 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
12 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:143:19)
13 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
14 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
15 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
16 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
17 _invoke1 (dart:ui/hooks.dart:153:13)
18 _dispatchPointerDataPacket (dart:ui/hooks.dart:107:5)

但以下代码运行正常:

_pushToPage2() async {
    String result = await Navigator.push(
         context, MaterialPageRoute(builder: (context) => Page2()));
    print("$tag $result");
}

【问题讨论】:

  • 您的问题现在是否得到解决,或者您在这个问题上需要更多帮助?我的回答是否有用并帮助您解决了问题?
  • 我遇到了同样的问题,因为没有真正有效的答案,我想它不支持用 NamedRoutes 返回一些东西

标签: android flutter


【解决方案1】:

对我来说,错误是另一个错误 (type 'MaterialPageRoute<dynamic>' is not a subtype of type 'Route<String>'),我通过将返回值声明为动态类型来解决它:

dynamic result = await Navigator.of(context).pushNamed("/page");

虽然这会失去一些类型安全性,但它对我来说很好。

【讨论】:

  • /page,你如何返回数据?
  • 可以像Navigator.pop(context, "any data");这样返回数据
  • 如何处理 Data 对象?无需将其序列化为字符串并返回。
  • @none 你可以传回你想要的任何对象。不限于String
  • 我认为这是一个相当肮脏的解决方案,因为它不像你说的那样尊重类型安全。请查看我的解决方案!
【解决方案2】:

只需在路由器中为MaterialPageRoute 声明工作类型Page2

case "/page2":
  return MaterialPageRoute<Page2>(...};

【讨论】:

    【解决方案3】:

    我也有同样的问题。最后我找到了解决方案。将结果转换为您的类型。

    例如:

    String result = await Navigator.of(context).pushNamed("/some_route")
    

    上面的代码会引发异常

    但是,你可以这样做:

    final result = await Navigator.of(context).pushNamed("/some_route") as String;
    

    上面的代码将按预期工作。

    【讨论】:

      【解决方案4】:

      提供的答案似乎都没有解决您的问题,因为他们建议您使用 dynamicvar 放弃类型安全。这是一个糟糕的解决方法。

      如果您打算在保持静态类型的同时使用pushNamed,您似乎想要为要存储结果的变量提供类型String,那么只有一种可能性:类型转换。

      所以不要像这样使用pushNamed() 作为generic method

      _pushToPage2() async {
          String result = await Navigator.pushNamed<String>(context, "/page2");
          print("$tag $result");
      }
      

      您可以像这样对方法结果进行类型转换:

      _pushToPage2() async {
          String result = await Navigator.pushNamed(context, "/page2") as String;
          print("$tag $result");
      }
      

      无法为pushNamed() 方法提供类型是Navigatorroute tables 的已知缺陷,如here 所述。

      【讨论】:

        【解决方案5】:

        在您的 main.dart 文件和您的 main Function 中定义 MaterialApp 小部件,并在其中定义我们应用的路由(屏幕)。

        main.dart:

        void main() {
          runApp( 
            new MaterialApp( 
              home: new Screen1(), 
              routes: <String, WidgetBuilder> { 
                '/screen1': (BuildContext context) => new Screen1(), 
                '/screen2' : (BuildContext context) => new Screen2() 
              },
            )
          );
        }
        

        屏幕1:

        class Screen1 extends StatelessWidget {
            @override
             Widget build(BuildContext context) {
                ...
              }
        }
        

        屏幕2:

        class Screen2 extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
               ...
            }
        }
        

        然后导航到我们要做的屏幕:

        Navigator.of(context).pushNamed('/screen2');
        

        asyncawiat 不是必需的,但如果您正在为例如进行异步编程;您正在查询 Firestore,并根据查询结果选择导航到新屏幕或选择显示错误。

        更多详情:routing and navigation in flutter

        编辑:

        要在屏幕之间传递数据,请将参数传递给 Screen2 构造函数并使用Navigator.push()。请记住,在 Navigator.pushNamed() 中,您只能传递上下文和路由名称,不能在其中传递参数。

         Navigator.push(context, new MaterialPageRoute(
                      builder: (BuildContext context) => new Screen2(new Color(0xFF66BB6A)),
                    ));
        

        屏幕2:

        class Screen2 extends StatelessWidget {
             Screen2(this.color);
             final Color color;
              @override
              Widget build(BuildContext context) {
                   ...
                }
         }
        

        【讨论】:

        • 如何将数据发送回父屏?我在您的代码中没有看到类似的内容。我错过了什么吗?
        • 您使用push()而不是pushNamed()传递数据请仔细阅读问题
        • @CopsOnRoad 我已经回答了我们不能从 pushNamed() 传递参数或数据
        • 所以,你的回答可能只是一开始就说你不能这样做,对不起!
        • @CopsOnRoad 好吧,我还看到 OP 询问有关从子屏幕取回数据的问题,我在回答中显示了这一点
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-10
        • 1970-01-01
        • 2022-12-15
        • 1970-01-01
        • 2022-01-12
        • 1970-01-01
        • 2021-12-15
        相关资源
        最近更新 更多