11
votes

I use pushNamed() to get return data from screen like this:

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

But there was something wrong with the code, this the full error stack trace:

E/flutter: [ERROR:flutter/shell/common/shell.cc(181)] Dart Error: Unhandled exception:
type 'MaterialPageRoute' is not a subtype of type '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. (package: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 (package: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)

But the following code is working properly:

_pushToPage2() async {
    String result = await Navigator.push(
         context, MaterialPageRoute(builder: (context) => Page2()));
    print("$tag $result");
}
4
Is your problem being solved now or you need some more help in this question? Did my answer is useful and helped you to solved your problem? - ArgaPK
I got the same question and as there is not really a answer that works I suppose its not supported to return something with NamedRoutes - Jonas

4 Answers

15
votes

For me, the error was a different one (type 'MaterialPageRoute<dynamic>' is not a subtype of type 'Route<String>'), and I solved it by declaring the returning value as a dynamic type:

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

While this loses some type safety, it works fine for me.

2
votes

Just declare the working type Page2 for MaterialPageRoute in the router

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

I have a same problem. And finally I found a solution. Cast your result to your type.

For example:

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

The code above will raise the exception.

But, you can do like this:

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

The code above will work as expected.

-1
votes

In your main.dart file and inside your main Function define MaterialApp widget, and inside it we define routes (screens) of our App.

main.dart:

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

Screen1:

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

Screen2:

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

And to Navigate to screens we do:

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

async and awiat is not needed but if you are doing async programming for e.g; you are querying Firestore and on the basis of the result of query, you choose to navigate to the new screen or choose to show the error.

For more details: routing and navigation in flutter

Edit:

To pass data between Screens, pass the argument to the Screen2 constructor and use Navigator.push(). Remember that in Navigator.pushNamed() you pass context and route name only, and you can't pass arguments in it.

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

Screen2:

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