How to transfer non-line data on a specified route to Flutter?

I have many screens, and I use Navigator . I would like to use "named routes", but I also need to pass non-linear (like images) to my next route.

I cannot use pushNamed() because I cannot pass pushNamed() data to it.

How can I use a named route + send non-string data?

+29
source share
7 answers

EDIT:

Now you can pass complex arguments to Navigator.pushNamed :

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

It can then be used in onGenerateRoute to configure route construction 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; } }, ); 
+39
source

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}'), ], ), ), ), ); } } 
+3
source

The Flutter cookbook shows how to go to a new page and pass non-string data to it.

Transferring data to the next page

I started with Navigator.pushedNamed() because it was simple and I did not have data to transfer. When my needs changed and I wanted to pass data, I switched to Navigator.push() .

Example:

 var nextPageData = {foo:'bar'}; Navigator.push( context, MaterialPageRoute(builder: (context) => MyNextPage(myData: nextPageData)) ); 
+2
source

To solve this problem, I developed a package

link: https://pub.dartlang.org/packages/navigate

It meets your expectations and is easy to use.

 Navigate.navigate(context, "home", transactionType:TransactionType.fromLeft , // optional replaceRoute: ReplaceRoute.thisOne, //optional arg: {"transactionType":TransactionType.fromLeft,"replaceRoute":ReplaceRoute.thisOne} //optional ); 
+1
source

I take images with the camera and then transfer them to the confirmation page, for example:

  ImagePicker.pickImage(source: source).then((File file) { Navigator.push( context, MaterialPageRoute( builder: (context) => MediaCaptured(file: file), )); }); 

You can easily do the same with any type of file or non-string data.

 var foo = "non-string data"; Navigator.push( context, MaterialPageRoute( builder: (context) => MediaCaptured(foo: foo), )); 

Name the next page of the route by class name, as described above.

Just make sure your new page accepts this in its constructor.

  // Stateful Widget class MediaCaptured extends StatefulWidget { MediaCaptured({ Key key, @required this.foo,}) : super(key: key); final var foo; } // StatelessWidget class MediaCaptured extends StatelessWidget { MediaCaptured(this.foo); var foo; } 
0
source

You can use the routes parameters of your application to pass arguments directly.

Like this:

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

In this case, a complete example would look like this:

 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); } 
0
source
 We can pass any type of arguments when declaring routes as constructor arguments as below, For example to send a list of Strings, List<String> titles = []; void main() => runApp( new MaterialApp( home: new FirstPage(), routes: <String, WidgetBuilder>{ "/SecondPage": (BuildContext context) => new SecondPage(titles), }, ), ); class FirstPage extends StatelessWidget { @override Widget build(BuildContext context) { return new Container( child: new RaisedButton(onPressed: () { Navigator.of(context).pushNamed('/SecondPage'); }), ); } } class SecondPage extends StatelessWidget { final List<String> titles; SecondPage(this.titles); @override Widget build(BuildContext context) { return new ListView.builder( itemBuilder: (context, index) { return new ListTile( title: new Text(titles[index]), ); }, ); } } 
-4
source

Source: https://habr.com/ru/post/1273554/


All Articles