Using onGenerateRoute it is easy to pass complex arguments when navigating a route using Navigator.pushNamed or Navigator.pushReplacementNamed
The minimum installation to show the concept will be
main.dart
import 'package:flutter/material.dart'; import 'package:navigator/routes.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Navigation Demo', theme: ThemeData( primarySwatch: Colors.teal, ), onGenerateRoute: (RouteSettings settings) { return MaterialPageRoute( builder: (BuildContext context) => makeRoute( context: context, routeName: settings.name, arguments: settings.arguments, ), maintainState: true, fullscreenDialog: false, ); }, ); } }
routes.dart
In the _buildRoute method _buildRoute we check the name of the route and _buildRoute arguments to the required type.
The disadvantage is that the type must be defined in advance if the required argument is not a simple type.
import 'package:flutter/material.dart'; import 'package:navigator/list.dart'; import 'package:navigator/details.dart'; Widget makeRoute( {@required BuildContext context, @required String routeName, Object arguments}) { final Widget child = _buildRoute(context: context, routeName: routeName, arguments: arguments); return child; } Widget _buildRoute({ @required BuildContext context, @required String routeName, Object arguments, }) { switch (routeName) { case '/': return ArticleList(); case '/ArticleView': Article article = arguments as Article; return ArticleView(article: article); default: throw 'Route $routeName is not defined'; } }
Views
list.dart
Create a route argument using a specific type, in our case Article .
import 'package:flutter/material.dart'; import 'package:navigator/details.dart' show Article; class ArticleList extends StatefulWidget { @override _ArticleListState createState() => _ArticleListState(); } class _ArticleListState extends State<ArticleList> { List<Article> articles = [ Article( id: 1, title: 'Article 1', author_name: 'Nilotpal', summary: 'Article 1 summary'), Article( id: 2, title: 'Article 2', author_name: 'Mike', summary: 'Article 2 summary'), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Articles'), ), body: Center( child: Column( children: <Widget>[ ListTile( title: Text('${articles[0].title}'), subtitle: Text('by ${articles[0].author_name}'), onTap: () { Navigator.of(context) .pushNamed('/ArticleView', arguments: articles[0]); }, ), ListTile( title: Text('${articles[1].title}'), subtitle: Text('by ${articles[1].author_name}'), onTap: () { Navigator.of(context) .pushNamed('/ArticleView', arguments: articles[1]); }, ), ], ), ), ); } }
details.dart
Define type for arguments
import 'package:flutter/material.dart'; class Article { final int id; final String author_name; final String title; final String summary; Article( {@required this.id, @required this.author_name, @required this.title, @required this.summary}); } class ArticleView extends StatelessWidget { final Article _article; ArticleView({@required Article article}) : _article = article; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('${_article.title}'), ), body: SafeArea( top: true, child: Center( child: Column( children: <Widget>[ Text('${_article.author_name}'), Text('${_article.summary}'), ], ), ), ), ); } }