Flutter: Advance Routing and Navigator (Part 2)
This Article is having two parts and this is second part.
- Flutter Advance Routing — Part 1: Talked about only Routing
- Flutter Advance Routing — Part 2: Talked about only Data Sharing
In this article, we will understand the implementation of data sharing while routing. There is three different way of doing that. I will discuss them one by one.
Sharing of data is very much important when we are moving from one to another screen. We see the medium article and we click on the author name we move to the author profile. How the profile pages know that for which author you have requested? These all are done using the data which is being shared while moving to the other page. There could be data or some object whatever you want to share you can share in a flutter application.
Example 1 : Simple Routing
This is one of the simplest ways of routing. Whenever anyone first learns about the routing and data sharing, they learn this particular approach.
You can share any kind of data i.e. String, integer, Map, List, Object, etc. In this example, we will share an object from one screen to the other screen.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: HomePage(),
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: RaisedButton(
onPressed: () {
User user = new User(name: 'Nitish', age: 18);
Route route =
MaterialPageRoute(builder: (context) => SecondHome(user: user));
Navigator.push(context, route);
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
final User user;
SecondHome({this.user});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('${this.user.name} - ${this.user.age}'),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class User {
final String name;
final int age;
User({this.name, this.age});
}
User Class
we have created the user class and we will pass the user object to the next page/screenSecondHome(user : user)
we are passing the user object to the next page/screenSecondHome({this.user})
we are initializing the user object here which is coming from the previous page/screen.
I don’t think this example need more explanation.
Example 2 : Named Routing
This is named route and I discussed this in the previous post. So I will only focus on the things which are new here.
In the last example, we had passed the data in Constructor
but here we don’t have direct/indirect access to the Constructor
of the SecondScreen. So, we need to do something else.
routes: <String, WidgetBuilder>{
'/home': (context) => HomePage(),
'/second': (context) => SecondHome(),
},
- This is how we defined routes
Navigator.pushNamed(context, '/second', arguments: user)
- In order to move to the next page, we have to tell the name of the routes. There is an optional argument in the pushNamed and that is called arguments.
arguments
accepts the Object. We can pass any kind of object here. - Now we have passed the data to the next screen.
RouteSettings settings = ModalRoute.of(context).settings;
- To access the data on our next screen we will need RouteSettings.
- Whenever we use the routes in our application the then we get RouteSettings.
- RouteSettings gives us access to the name of the route and parameter which is being passed to the routes.
Using RouteSettings we are getting the data which is being passed from the previous screen. Let’s see the full source code.
Full Source Code
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
initialRoute: '/',
routes: <String, WidgetBuilder>{
'/': (context) => HomePage(),
'/second': (context) => SecondHome(),
},
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
User user = new User(name: 'Nitish', age: 18);
Navigator.pushNamed(context, '/second', arguments: user);
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
User user;
@override
Widget build(BuildContext context) {
RouteSettings settings = ModalRoute.of(context).settings;
user = settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('${this.user.name} - ${this.user.age}'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class User {
final String name;
final int age;
User({this.name, this.age});
}
RouteSettings
will only available when you are using routes in MaterialApp. In other cases, if you will try to call theRouteSettings
then you will null as value.
Example 3 : onGenerateRoute
When you will be using onGenerateRoute then
RouteSettings
will be unavailable in the SecondHome.
So, How we can send the data to the next screen if we can’t access to the RouteSettings
.
We will use a mixture of RouteSettings and Constructor to send the data to the next screen. This approach is one of the best approaches to doing routing in any real-world application.
So, how we can do that?
- We don’t have direct access to the
Constructor
but we do have indirect access to theConstructor
of the SecondScreen. - We don’t have access to the
RouteSetting
inside theSecondHome
but we have access to that outside ofSecondHome
Let’s understand how we are having indirect access to the RouterSetting
and how we can use the constructor of the SecondHome
.
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context)=> HomePage());
break;
case '/second':
return MaterialPageRoute(builder: (context)=> SecondPage());
break;
}
- Here you can see that we are having access to the
RouteSettings
. If you remember in our previous example I had access the arguments usingRouteSettings
. So, here also we will use the same approach.
See this example
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => HomePage());
break;
case '/second':
User user = settings.arguments;
return MaterialPageRoute(
builder: (context) => SecondHome(user: user),
);
break;
}
},
- Here we are having access to the
RouteSettings
andarguments.
- Extract the
arguments
and pass that to the constructor of theSecondHome.
I hope you got the idea that how you can share the data when you are using onGenerateRoute
. Let’s see the full source code
Full Source Code
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: HomePage(),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => HomePage());
break;
case '/second':
User user = settings.arguments;
return MaterialPageRoute(
builder: (context) => SecondHome(user: user),
);
break;
}
},
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
User user = new User(name: 'Nitish', age: 18);
Navigator.pushNamed(context, '/second', arguments: user);
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
final User user;
SecondHome({this.user});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('${this.user.name} - ${this.user.age}'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class User {
final String name;
final int age;
User({this.name, this.age});
}
Hello World, If you want code for all these example then you need to wait for some time. I’ll add GitHub repository link soon.
You can follow me get the get Notified first by GitHub itself
📝 Read this story later in Journal.
👩💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.