How do I pass non-string data to a named route in Flutter?

EDIT:

It is now possible to pass complex arguments to Navigator.pushNamed:

String id;
Navigator.pushNamed(context, '/users', arguments: id);

It can then be used within onGenerateRoute to customize route building with these arguments:

MaterialApp(
  title: 'Flutter Hooks Gallery',
  onGenerateRoute: (settings) {
    final arguments = settings.arguments;
    switch (settings.name) {
      case '/users':
        if (arguments is String) {
          // the details page for one specific user
          return UserDetails(arguments);
        }
        else {
          // a route showing the list of all users
          return UserList();
        }
      default:
        return null;
    }
  },
);

You can use the parameter routes of your App for directly passing arguments.

Like this:

  routes: {
    HomePage.route: (_) => HomePage(),
    DetailsPage.route: (context) =>
        DetailsPage(ModalRoute.of(context).settings.arguments),
  },

In this case, the complete example will look like the next:

import 'package:flutter/material.dart';

    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          initialRoute: HomePage.route,
          routes: {
            HomePage.route: (_) => HomePage(),
            DetailsPage.route: (context) =>
                DetailsPage(ModalRoute.of(context).settings.arguments),
          },
        );
      }
    }

    class HomePage extends StatelessWidget {
      static const String route = '/';

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Container(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              Navigator.pushNamed(context, '/details',
                  arguments: ScreenArguments(
                    'My Details',
                    'Some Message',
                  ));
            },
          ),
        );
      }
    }

    class DetailsPage extends StatelessWidget {
      static const String route = '/details';

      final ScreenArguments arguments;

      DetailsPage(this.arguments);

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(arguments.title),
          ),
          body: Center(
            child: Text(arguments.message),
          ),
        );
      }
    }

    class ScreenArguments {
      final String title;
      final String message;

      ScreenArguments(this.title, this.message);
    }

By Using Maps

While pushing the arguments u can push that in map form and can do the same while extracting them.

e.g.

While Pushing

Navigator.of(context).pushNamed(
              'second',
              arguments: {
                'title':'This is a String',
                       or
                 'Fx': This could be any widget or Function
              }

While Extracting the arguments in the target page

final routes=ModalRoute.of(context).settings.arguments as Map<String,String>;

    return Scaffold(
      appBar: AppBar(
              title: Text(routes['title']),
              ),
      body: Container(
        child: Center(
          child: RaisedButton(
            child: Text("Back"),
            onPressed: ()=>Navigator.of(context).pop(),
          ),
        ),
      ),
    );

and choose your map accordingly accordingly