Route management is essential for any application of Flutter. This article explains the use of router-related methods and changes in the routing stack.
There are two important concepts in Flutter routing management:
- Route: The Route is an abstraction of the application page. It corresponds to the Activity in Android and the ViewController in iOS, and is managed by the Navigator.
- Navigator: Navigator is a component that manages and maintains a stack-based history of page jumps through push and pop.
Push and pop
Suppose there are two pages A and B, and there is A button in A, click to jump to page B, page A code:
class APage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
child: RaisedButton(
child: Text('A page'),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
returnBPage(); })); },),); }}Copy the code
B Page code:
class BPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: RaisedButton(
child: Text('B page'), onPressed: () { }, ), ), ); }}Copy the code
When the application is on page A, there is only A in the routing stack, click the button to jump to page B, there is B and A in the routing stack, and B is at the top of the stack.
Click the button on page B to return to page A and modify the button clicking event on page B:
RaisedButton(
child: Text('B page'), onPressed: () { Navigator.of(context).pop(); },)Copy the code
Routing stack changes:
The effect of the above case is to jump from page B to page A. Can push method also be used? Modify button click events on page B:
RaisedButton(
child: Text('B page'),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
returnAPage(); })); },)Copy the code
In effect, we can also jump to page A, routing stack:
Can we use push instead of pop? The answer is definitely no,
- Imagine the following scenario: enter the shopping App, display the shopping list, click one of them to enter the product details page, use push to enter the shopping list again, and then enter the product details page… And so on, the routing stack will store a large number of routes of shopping list and commodity details page. Click the back button, and the shopping list and commodity details page will be displayed repeatedly.
- Page switch routing animations push and pop are different.
MaybePop and canPop
In the example above, what if you click the button on page A to call pop directly?
RaisedButton(
child: Text('A page'), onPressed: () { Navigator.of(context).pop(); },)Copy the code
The routing stack changes when pop is called:
The routing stack is empty, there are no pages to display, the application will exit or a black screen, which is not what a good user experience should be. In this case, maybePop can be used, and maybePop only pops up routes when there are popup routes on the routing stack.
The above example executes maybePop on page A:
RaisedButton(
child: Text('A page'), onPressed: () { Navigator.of(context).maybePop(); },)Copy the code
The route will not pop up after clicking, because there is only A in the current route stack. MaybePop on page B will return to page A.
CanPop can also be used to determine whether the current pop can be performed:
RaisedButton(
child: Text('B page'),
onPressed: () {
if(Navigator.of(context).canPop()){ Navigator.of(context).pop(); }},)Copy the code
pushNamed
PushNamed is the way to name the route. The route name needs to be configured in the MaterialApp:
MaterialApp(
title: 'Flutter Demo',
routes: <String, WidgetBuilder>{
'/A': (context) => APage(),
'/B': (context) => BPage(),
},
home: Scaffold(
body: APage(),
),
)
Copy the code
Jump from A to B:
RaisedButton(
child: Text('A page'),
onPressed: () {
Navigator.of(context).pushNamed('/B'); },)Copy the code
PushReplacementNamed and popAndPushNamed
There are three pages A, B and C, page A jumps to B by pushNamed:
RaisedButton(
child: Text('A page'),
onPressed: () {
Navigator.of(context).pushNamed('/B'); },)Copy the code
Select * from B where pushReplacementNamed;
RaisedButton(
child: Text('B page'),
onPressed: () {
Navigator.of(context).pushReplacementNamed('/C'); },)Copy the code
Click the C page button to execute pop:
RaisedButton(
child: Text('C page'),
onPressed: () {
if(Navigator.of(context).canPop()){ Navigator.of(context).pop(); }},)Copy the code
Click the “C” button to return to “A” instead of “B”, because “B” uses the pushReplacementNamed redirect. The route stack changes:
Jump from page B to page C using popAndPushNamed:
RaisedButton(
child: Text('B page'),
onPressed: () {
Navigator.of(context).popAndPushNamed('/C'); },)Copy the code
The popAndPushNamed routing stack is the same as pushReplacementNamed, the only difference is that popAndPushNamed has a B page exit animation.
PopAndPushNamed and pushReplacementNamed make the current page not in the routing stack, so it cannot be returned via POP.
Applicable scenarios:
- Welcome screen: The application will enter the welcome screen first and then the home page. After entering the home page, it should not enter the welcome screen again.
- Login page: The login page is displayed after the login is successful. Press the back button to enter the login page.
pushNamedAndRemoveUntil
In the following scenarios, the home page of the application is displayed, and the login page is displayed. Then the registration page or the forgotten password page is displayed. In this scenario, you can use pushNamedAndRemoveUntil if you do not want to return to another login page.
There are four pages A, B, C and D. A enters B page through push, B enters C page through push, C enters D page through pushNamedAndRemoveUntil and deletes the route up to /B in the routing stack at the same time.
RaisedButton(
child: Text('C page'),
onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil('/D', ModalRoute.withName('/B')); },),Copy the code
D page button to execute pop:
RaisedButton(
child: Text('D page'), onPressed: () { Navigator.of(context).pop(); },)Copy the code
Route stack changes from page C to page D:
Navigator.of(context).pushNamedAndRemoveUntil('/D', ModalRoute.withName('/B'));
Copy the code
D is displayed, and all routes from D to B are deleted. If all routes are deleted, only D is saved.
Navigator.of(context).pushNamedAndRemoveUntil('/D', (Route route)=>false);
Copy the code
Route stack changes:
popUntil
Has the following scene, in the entry of the new company, need to fill in all kinds of information, the information is divided into different parts, such as basic information, work, family, etc., these different modules in different pages, fill in the information when can return to the previous page, also can cancel, cancel to return to the home page, this scenario can use popUntil, Pop all the way to the specified page.
There are four pages A, B, C and D. Page D is returned to page A through popUntil. The code of page D is:
RaisedButton(
child: Text('D page'),
onPressed: () {
Navigator.of(context).popUntil(ModalRoute.withName('/A')); },)Copy the code
Route stack changes:
To transfer data
In the following scenario, click the page of commodity list to jump to the page of commodity details. The page of commodity details requires the unique ID of the commodity or the detailed data of the commodity. There are two ways to transfer data:
The first way is through the constructor:
class ProductDetail extends StatelessWidget {
final ProductInfo productInfo;
const ProductDetail({Key key, this.productInfo}) : super(key: key);
@override
Widget build(BuildContext context) {
returnContainer(); }}Copy the code
Jump code:
Navigator.of(context).push(MaterialPageRoute(builder: (context){
return ProductDetail(productInfo: productInfo,);
}));
Copy the code
This mode cannot be used to forward named routes.
The second way: set parameters by naming routes:
A page passes data,
RaisedButton(
child: Text('A page'),
onPressed: () {
Navigator.of(context).pushNamed('/B',arguments: 'from A'); },)Copy the code
Page B receives data via modalroute.of (context).settings.arguments:
RaisedButton(
child: Text('${ModalRoute.of(context).settings.arguments}'),
onPressed: () {
Navigator.of(context).pushNamed('/C'); },)Copy the code
Return the data
B page return code:
RaisedButton(
child: Text('${ModalRoute.of(context).settings.arguments}'),
onPressed: () {
Navigator.of(context).pop('Return from B'); },)Copy the code
Page A receives returned data:
class APage extends StatefulWidget {
@override
_APageState createState() => _APageState();
}
class _APageState extends State<APage> {
String _string = 'A page';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: RaisedButton(
child: Text(_string),
onPressed: () async {
var result =
await Navigator.of(context).pushNamed('/B', arguments: 'from A'); setState(() { _string = result; }); },),),); }}Copy the code
Push related methods return the Future type and await the result with await.
communication
Lao Meng Flutter blog (330 controls usage + practical primer series) : laomengit.com