Flutter路由管理
路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,所谓路由管理,
就是管理页面之间如何跳转,通常也可被称为导航管理。Flutter中的路由管理和原生开发类似,无论是Android还是iOS,
导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作,
而路由管理主要是指如何来管理路由栈。MaterialPageRoute
dart
1 | MaterialPageRoute({ |
- builder 是一个WidgetBuilder类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。我们通常要实现此回调,返回新路由的实例。
- settings 包含路由的配置信息,如路由名称、是否初始路由(首页)。
- maintainState:默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false。
- fullscreenDialog表示新的路由页面是否是一个全屏的模态对话框,在iOS中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。
示例
创建一个新路由,命名“NewRoute”
dart1
2
3
4
5
6
7
8
9
10
11
12
13class NewRoute extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New route"),
),
body: Center(
child: Text("This is new route"),
),
);
}
}再 HomeWidget 中添加一个按钮
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39void main()=>runApp(new MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return new MaterialApp(
title: "demo1",
home: HomeWidget()
);
}
}
class HomeWidget extends StatelessWidget{
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("title"),
),
body: new Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
FlatButton(
child: Text("open new route"),
textColor: Colors.blue[400],
onPressed: () {
Navigator.push(
context, MaterialPageRoute(
builder: (context) {return NewRoute();},
maintainState: false,
fullscreenDialog: false
));
},
)
],
),
),
);
}
}
Navigator
Navigator是一个路由管理的组件,它提供了打开和退出路由页方法。Navigator通过一个栈来管理活动路由集合。
通常当前屏幕显示的页面就是栈顶的路由。Navigator提供了一系列方法来管理路由栈- push(BuildContext context, Route route)
将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据。 - pop(BuildContext context, [ result ])
将栈顶路由出栈,result为页面关闭时返回给上一个页面的数据。Navigator 还有很多其它方法,如Navigator.replace、Navigator.popUntil等,详情请参考API文档或SDK源码注释,在此不再赘述。
路由传值
很多时候,在路由跳转时我们需要带一些参数,比如打开商品详情页时,
我们需要带一个商品id,这样商品详情页才知道展示哪个商品信息;
又比如我们在填写订单时需要选择收货地址,打开地址选择页并选择地址后,
可以将用户选择的地址返回到订单页等等。下面我们通过一个简单的示例来演示新旧路由如何传参新建一个子页面
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import 'package:flutter/material.dart';
class TipRoutr extends StatelessWidget{
TipRoutr({
Key key,
this.text,
}):super(key:key);
final String text;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("tishi"),
),
body: Padding(
padding: EdgeInsets.all(18),
child: Center(
child: Column(
children: <Widget>[
Text("text"),
RaisedButton(
onPressed: ()=>Navigator.pop(context,'我是返回值'),
child: Text("返回"),
)
],
),
),
),
);
}
}新建一个父页面
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import 'package:flutter/material.dart';
import 'package:flutter_app1/router_Demo/TipRoute.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget{
Widget build(BuildContext context) {
return MaterialApp(
title: '123',
home: Scaffold(
appBar: AppBar(
title: Text("123"),
),
body: RouterTestRoute(),
),
theme: ThemeData(colorScheme: ColorScheme.light(background: Colors.redAccent)),
);
}
}
class RouterTestRoute extends StatelessWidget{
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () async{
var result = await Navigator.push(context, MaterialPageRoute(
builder: (context){
return TipRoutr(
text: "woshi tishi",
);
},
),
);
print("luyou $result");
},
child: Text("open Tip"),
),
);
}
}
- 提示文案“我是提示xxxx”是通过TipRoute的text参数传递给新路由页的。我们可以通过等待Navigator.push(…)返回的Future来获取新路由的返回数据。
- 在TipRoute页中有两种方式可以返回到上一页;第一种方式时直接点击导航栏返回箭头,第二种方式是点击页面中的“返回”按钮。这两种返回方式的区别是前者不会返回数据给上一个路由,而后者会。下面是分别点击页面中的返回按钮和导航栏返回箭头后,RouterTestRoute页中print方法在控制台输出的内容:
I/flutter (27896): 路由返回值: 我是返回值
I/flutter (27896): 路由返回值: null命名路由
谓“命名路由”(Named Route)即有名字的路由,我们可以先给路由起一个名字,
然后就可以通过路由名字直接打开新的路由了,这为路由管理带来了一种直观、简单的方式。定义routes
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import 'package:flutter/material.dart';
import 'pages3-22/DefaultPage.dart';
import 'pages3-22/HomePage.dart';
import 'pages3-22/ListPage.dart';
import 'pages3-22/MePage.dart';
import 'pages3-22/SearchPage.dart';
void main() => runApp(App());
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: MyApp(),
routes: {
"/HomePage": (context) => HomePage(),
"/DefaultPage": (context) => DefaultPage(),
"/ListPage": (context) => ListPage(),
"/MePage": (context) => MePage(),
"/Search": (context) => SearchPage(),
},
);
}
}在页面写跳转按钮
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
// 命名路由的跳转方式
Navigator.pushNamed(context, "/Search");
},
child: Text("跳转到search页面并且传递id"),
),
],
),
);
}
}跳转的页面
dart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import "package:flutter/material.dart";
class SearchPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("查询页面"),
),
body: Container(
child: Text("SearchPage"),
),
);
}
}
命名路由传参
待更!
路由替换
dart
1 | Navigator.pushReplacementNamed(context,'/routerName'); |
返回到上一个页面
dart
1 | Navigator.of(context).pop(); |
返回到根页面
dart
1 | Navigator.of(context).pushAndRemoveUntil( |

