Table of contents
1.2.1 Future push(BuildContext context, Route route)
1.2.2 bool pop(BuildContext context, [ result ])
1.2.3 Future pushNamed(BuildContext context, String routeName,{Object arguments})
1.3 Non-named route passing value
1.4.3 Open a new routing page through the routing name
1.4.4 Named route parameter passing
1.4.5 Adapt non-named route value transfer
0 Preface
This article is a study and summary of the preface to the second edition | "Flutter in Practice·Second Edition" (flutterchina.club) .
1 Routing management
- Route usually refers to page in mobile development, which has the same conceptual meaning as Route in single-page application in web development.
- Route usually refers to an Activity in Android and a ViewController in iOS.
- The so-called routing management is to manage how to jump between pages, which is usually also called navigation management.
- Routing management in Flutter is similar to native development. Whether it is Android or iOS, navigation management will maintain a routing stack. The routing push operation corresponds to opening a new page, and the routing pop operation corresponds to the page closing operation. Routing management mainly refers to how to manage the routing stack.
1.1 MaterialPageRoute
MaterialPageRoute
Inherited fromPageRoute
class,PageRoute
class is an abstract class that represents a modal routing page that occupies the entire screen space. It also defines related interfaces and properties for transition animation during routing construction and switching.MaterialPageRoute
It is a routing component provided by the Material component library. It can implement routing switching animations consistent with the platform page switching animation style for different platforms :
- For Android, when a new page is opened, the new page will slide from the bottom of the screen to the top of the screen; when the page is closed, the current page will slide from the top of the screen to the bottom of the screen and then disappear, while the previous page will be displayed on the screen.
- For iOS, when a page is opened, the new page will slide from the right edge of the screen to the left side of the screen until all the new pages are displayed on the screen, while the previous page will slide from the current screen to the left side of the screen and disappear; when When closing a page, the opposite is true. The current page will slide out from the right side of the screen, and the previous page will slide in from the left side of the screen.
- If you want to customize the route switching animation, you can inherit PageRoute yourself to implement it.
MaterialPageRoute({
/*
用于构建路由页面的具体内容,返回值是一个新路由的widget实例。
*/
WidgetBuilder builder,
/*
包含路由的配置信息,如路由名称、是否初始路由(首页)。
*/
RouteSettings settings,
/*
是否维护原路由内存状态,默认true, 即当入栈一个新路由时,原来的路由仍然会被保存在内存中。
如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为 false
*/
bool maintainState = true,
/*
表示新的路由页面是否是一个全屏的模态对话框,在 iOS 中,
如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)
*/
bool fullscreenDialog = false,
})
1.2 Navigator
Navigator
It is a routing management component that provides methods to open and exit the routing page .Navigator
A stack is used to manage the set of active routes.- Usually the page currently displayed on the screen is the route at the top of the stack.
1.2.1 Future push(BuildContext context, Route route)
Open the unnamed route page : push the given route onto the stack (i.e. open a new page). The return value is an
Future
object used to receive the return data when the new route is popped off the stack (i.e. closed).
1.2.2 bool pop(BuildContext context, [ result ])
Close the routing page : Pop the top route from the stack (that is, close the page currently displayed on the screen). The return value is a bool object.
result
The data returned to the previous page when the page is closed.
1.2.3 Future pushNamed(BuildContext context, String routeName,{Object arguments})
Open the named route page : push the given route onto the stack (i.e. open a new page). The return value is an
Future
object used to receive the return data when the new route is popped off the stack (i.e. closed).
1.3 Non-named route passing value
/*
创建一个TipRoute路由,它接受一个提示文本参数,负责将传入它的文本显示在页面上,
另外TipRoute中添加一个“返回”按钮,点击后在返回上一个路由的同时会带上一个返回参数
*/
class TipRoute extends StatelessWidget {
TipRoute({
Key key,
required this.text, // 接收一个text参数
}) : super(key: key);
final String text;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("提示"),
),
body: Padding(
padding: EdgeInsets.all(18),
child: Center(
child: Column(
children: <Widget>[
Text(text),
ElevatedButton(
onPressed: () => Navigator.pop(context, "我是返回值"),
child: Text("返回"),
)
],
),
),
),
);
}
}
/*
打开新路由TipRoute的代码:
*/
class RouterTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
onPressed: () async {
// 打开`TipRoute`,并等待返回结果
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return TipRoute(
// 路由参数
text: "我是提示xxxx",
);
},
),
);
//输出`TipRoute`路由返回结果
print("路由返回值: $result");
},
child: Text("打开提示页"),
),
);
}
}
1.4 Named routing
"Named Route" is a route with a name
1.4.1 Routing table
To use named routing, you must first provide and register a routing table (routing table) so that the application knows which name corresponds to which routing component.
Definition of routing table: It is a Map,
- key is the name of the route, which is a string;
- value is a builder callback function, used to generate the corresponding routing widget.
- When opening a new route through the route name, the application will find the corresponding WidgetBuilder callback function in the routing table based on the route name, and then call the callback function to generate the route widget and return it.
Map<String, WidgetBuilder> routes;
1.4.2 Register routing table
In
MaterialApp中
, addroutes
attributes, register routing table
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context) => NewRoute(),
... // 省略其他路由注册信息
} ,
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
/* 将home页面也注册为命名路由 */
MaterialApp(
title: 'Flutter Demo',
initialRoute:"/", //名为"/"的路由作为应用的home(首页)
theme: ThemeData(
primarySwatch: Colors.blue,
),
//注册路由表
routes:{
"new_page":(context) => NewRoute(),
"/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
}
);
1.4.3 Open a new routing page through the routing name
onPressed: () {
//打开命名路由页面
Navigator.pushNamed(context, "new_page");
//打开非命名路由页面
//Navigator.push(context,
// MaterialPageRoute(builder: (context) {
// return NewRoute();
//}));
},
1.4.4 Named route parameter passing
/*
1.先注册一个路由:
*/
routes:{
"new_page":(context) => EchoRoute(),
} ,
/*
2.在路由页通过RouteSetting对象获取路由参数:
*/
class EchoRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
//获取路由参数
var args=ModalRoute.of(context).settings.arguments;
//...省略无关代码
}
}
/*
3.在打开路由时传递参数
*/
Navigator.of(context).pushNamed("new_page", arguments: "hi");
1.4.5 Adapt non-named route value transfer
In 1.3 Non-named routing by value ,
TipRoute
atext
parameter is accepted. IfTipRoute
the routing page is registered in the routing table, how toTipRoute
open it through the routing name and implement parameter passing without changing the source code?
/*
1.将TipRoute注册到路由表,同时传递text参数
*/
MaterialApp(
routes: {
"tip2": (context){
return TipRoute(text: ModalRoute.of(context)!.settings.arguments.toString());
},
},
);
/*
2.TipRoute源码,见【 1.3 非命名路由传值 】
*/
/*
3.在打开路由时传递参数值
*/
Navigator.of(context).pushNamed("tip2", arguments: "你好吗");
1.5 Route generation hook
- The route generation hook refers to the properties
MaterialApp
inonGenerateRoute
onGenerateRoute
Only takes effect on named routesonGenerateRoute
It may be called when opening a named route: when calling to open aNavigator.pushNamed(...)
named route, if the specified route name has been registered in the routing table, the function in the routing table will be calledbuilder
to generate the routing component; if it is not registered in the routing table, it will Will be calledonGenerateRoute
to generate routes.onGenerateRoute
You can perform more detailed operations on routing and jump to different pages according to different situations. Permission control can also be performed.onGenerateRoute
Examples of applicable scenarios: Suppose we want to develop an e-commerce App. When users are not logged in, they can view store, product and other information, but transaction records, shopping carts, user personal information and other pages need to be logged in before they can be viewed.
MaterialApp(
... //省略无关代码
onGenerateRoute:(RouteSettings settings){
//返回一个Route<dynamic>
return MaterialPageRoute(builder: (context){
String routeName = settings.name;
/*
如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,引导用户登录;
其他情况则正常打开路由。
*/
}
);
}
);
1.6 Summary
In actual development, it is recommended to use named routing management, which will bring the following benefits:
- The semantics are clearer.
- The code is easier to maintain; if you use anonymous routing, you must
Navigator.push
create a new routing page where it is called. This not only requires importing the dart file of the new routing page, but also such code will be very scattered.- You can
onGenerateRoute
do some global routing jump pre-processing logic.
navigatorObservers
There are alsoonUnknownRoute
two callback attributes in the routing MaterialApp :
navigatorObservers
Can monitor all routing jump actionsonUnknownRoute
Called when opening a named route that does not exist