Flutter和Dart系列之八:路由

释放双眼,带上耳机,听听看~!

截至目前为止,我们的Widget都是在一个页面上实现的。对于一个App而言,不可能只有一个页面。那么在Flutter怎样实现页面间的跳转呢?

启动一个新的页面:Navigator.push(),类似Android中的startActivity


1
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
1class MyApp extends StatelessWidget {
2
3  @override
4  Widget build(BuildContext context) {
5    return MaterialApp(
6      title: 'Flutter App',
7      home: FirstRoute(),
8    );
9  }
10}
11
12class FirstRoute extends StatelessWidget {
13  @override
14  Widget build(BuildContext context) {
15    return Scaffold(
16      appBar: AppBar(
17        title: Text("First Route"),
18      ),
19      body: Center(
20          child:  RaisedButton(
21            child: Text("go to second route"),
22            onPressed: () {
23                Navigator.push(context,
24                  MaterialPageRoute(builder: (context) => SecondRoute()));
25            }),
26      )),
27    );
28  }
29}
30
31class SecondRoute extends StatelessWidget {
32
33  @override
34  Widget build(BuildContext context) {
35    return Scaffold(
36        appBar: AppBar(
37          title: Text("Second Route"),
38        ),
39        body: Center(
40          child: Column(
41            mainAxisAlignment: MainAxisAlignment.center,
42            children: <Widget>[
43              RaisedButton(
44                  child: Text("go back"),
45                  onPressed: () {
46
47                  }),
48            ],
49          ),
50        ));
51  }
52}
53

Navigator.push()方法接收两个参数:

  • BuildContext
    • Route:这里使用了MaterialPageRoute,而这个路由对象有需要一个WidgetBuilder对象:


1
2
1typedef WidgetBuilder = Widget Function(BuildContext context);
2

所以只需要返回一个Widget对象即可。可见,在Flutter中,一个Route就是一个Widget。

  • 启动新页面时携带数据

在Android中,我们在启动一个新的Activity时,可以使用intent来携带一些数据传递给下一个Activity使用。而在Flutter中更直接:由于我们是直接创建了一个SecondRoute对象作为返回值,那么我们可以直接将需要携带的数据通过构造器传递过去即可。例如:


1
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
1class SecondRoute extends StatelessWidget {
2  SecondRoute({this.data});
3
4  final String data;
5
6  @override
7  Widget build(BuildContext context) {
8    return Scaffold(
9        appBar: AppBar(
10          title: Text("Second Route"),
11        ),
12
13    body: Center(
14      child: Column(
15        mainAxisAlignment: MainAxisAlignment.center,
16        children: <Widget>[
17          RaisedButton(
18             child: Text("go back"),
19             onPressed: () {
20
21             }),
22          Text(data)
23        ],
24      ),
25    ));
26  }
27}
28
29Navigator.push(context, MaterialPageRoute(builder: (context) =>
30                    SecondRoute(data: "hello world")));
31

这样我们就可以在SecondRoute中使用我们传入的data了。 

  • 从当前页面返回: Navigator.pop(),类似Anroid的finish()方法

我们来实现SecondRoute中的RaisedButton的点击回调:


1
2
1Navigator.pop(context);
2
  • 从当前页面返回并携带数据到上一个页面:


1
2
1Navigator.pop(context, "Welcome");//直接将要返回的数据作为pop方法的第二个参数
2

那么我们在FirstRoute中怎么去接收页面返回的数据呢,它可没有onActivityResult回调。这里会涉及到Dart语言本身的语法,所以我们需要先停一下。

  • await和async

在Android中或者说在Java中,我们要想拿到异步调用的返回结果,通常(Java中也可以通过Future和Callable来实现异步操作带返回值)是通过接口回调的方式,将结果作为回调方法的参数返回回来。就比如对于一个线程,无论是通过继承Thread类还是通过实现Runnable接口的方式,在run方法里我们都不能够直接返回结果。而在Dart中,我们只需要借助一个关键字await:


1
2
3
4
1var info = await queryUserInfo();  // 假定这个queryUserInfo是从数据库中查询或
2                                    //者网络请求,是异步操作
3showUserInfo(info);     // 借助于await关键字,我们可以直接拿到异步操作的结果                          
4

是不是很强大,而且更加简单!单独的await关键字的使用还不行,我们还需要再使用await的方法上加上async关键字,表示该方法是一个异步方法。


1
2
3
4
5
1loadData() async{
2    var info = await queryUserInfo();
3    showUserInfo(info);
4}  
5

await有几个注意点:

  • await后面的表达式一般都返回一个Future类型的对象,即使表达式本身返回的不是一个Future对象,也会被编译器自动包装成一个Future对象

    • await并不是会一直停在那等着,因为这样它不就会白白占据CPU的资源吗?相当于会进入一个阻塞的状态,并且await后面的代码也不会执行,会等到await有返回值,才会继续执行。
  • 回到我们之前的问题中来,有了第5条知识点,我们可以有如下代码:


1
2
3
4
5
6
1_navigateAndDisplayResult(BuildContext context) async {
2    final result = await Navigator.push(
3        context, MaterialPageRoute(builder: (context) =>
4        SecondRoute("hello world")));//这个result就是"welcome"
5}        
6
  • Flutter还支持通过路由名来实现页面跳转:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1MaterialApp(
2  //    声明路由映射
3  routes: {SecondRoute.routeName: (context) => SecondRoute()},
4  title: 'Flutter Demo',
5  home: FirstRoute(),
6);  
7
8class SecondRoute extends StatelessWidget {
9    static const routeName = '/second';
10}  
11
12//使用处
13Navigator.pushNamed(context, SecondRoute.routeName);
14

这种方式的优点就是耦合性低,更加直观,缺点就是不能动态在页面间传递数据。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ lambda表达式

2022-1-11 12:36:11

安全技术

40种网页常用小技巧

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索