Named route navigation error: type 'MaterialPageRoute<dynamic>' is not a subtype of type 'Route<String>'

Blindingly obvious in hindsight.

I had added the String type-hint in Navigator.pushNamed<String>() as I thought I could receive a typed value back from the call. Removing that and receiving it into a var solved the problem.

Leaving this up for anyone else who gets themselves into the same state.


Change this:

     MyType result = await Navigator.pushNamed(
                context,
                MyPage.routeName,
                arguments: PageArguments(myArg);

to:

     var result = await Navigator.pushNamed(
                context,
                MyPage.routeName,
                arguments: PageArguments(myArg);

It does make sense to have the type hints, it helps with debugging and lets the IDE flag when the type is not what you expect. (Big fan of strong typing where possible)

And you CAN do this with your named routes - Hooray!

You've implemented your route handling with the routes attribute of the MaterialApp but as you have found there is nowhere to add a return type of the route you are creating.

routes: {
  '/second': (BuildContext context) => SecondPage(),
}

This means any instance passed to it must have return type dynamic and throws an error for anything else.

onGenerateRoute

In order to specify the return type, it takes a little more code and the use of the onGenerateRoute property of 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,
        );
    }
)

This will now handle the pushNamed<String>('/second') - And There Was Much Rejoicing!

Tags:

Flutter