Background
Flutter provides two different navigation options.
Option 1. Use Widget class in MaterialPageRoute.
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
The key part.
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
Use the Navigator push method and pass the SecondRoute instance to MaterialPageRoute contructor.
If need to pass the paramter.
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
// The parameter passed via SecondRoute constructor.
MaterialPageRoute(builder: (context) => SecondRoute(message: 'The message for second view.')),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
// This is the parameter the SecondRoute needs.
final String message;
SecondRoute({@required this.message});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
Option 2. Use route.
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
The key part.
Navigator.pushNamed(context, '/second');
Also need to register the routes in MaterialApp.
void main() {
runApp(MaterialApp(
title: 'Named Routes Demo',
// Start the app with the "/" named route. In our case, the app will start
// on the FirstScreen Widget
initialRoute: '/',
routes: {
// When we navigate to the "/" route, build the FirstScreen Widget
'/': (context) => FirstScreen(),
// When we navigate to the "/second" route, build the SecondScreen Widget
'/second': (context) => SecondScreen(),
},
));
}
If need to pass the paramter.
// When the user taps the button, navigate to a named route
// and provide the arguments as an optional parameter.
Navigator.pushNamed(
context,
'/second',
arguments: 'The message for second view.',
);
Need to do some extra work to get the parameter.
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Gets the parameter from the route. Any type of the parameter is allowed.
final String message = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
The two options
The question
Official References
Navigate to a new screen and back
Navigate with named routes
Pass arguments to a named route
I think there shouldn't be use one or the other, why not both, but this depends on the project structure and the product requirements.
I usually do the following:
If the new screen depends on some parameters, any parameters, I will use your first option, I like a lot to specify the dependencies of a class in it's constructor, in this case, in the widget constructor.
If I already have a screen that has dependencies I will not mix named routes with "unnamed" routes.
For special screens, for example a root screen in a tab navigation, that has simple navigation (like, help, about us, T&C), I will usually use a named route navigation.
In my opinion, your first option is more reliable if the screen has dependencies, you'll avoid a lot of errors and you'll get the type check and I think it's easier to extend and maintain.
The second option, is for simple navigation.
So in conclusion, in my opinion, if the framework provides multiple ways of doing one thing, you shouldn't go with "this OR the other", usually it's best to go "this AND the other", you should think of common cases when one way works better and if you find cases where the other implementation works better, don't be afraid to use it, after all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With