11.Flutter路由管理与Navigator基础使用

前言

咱们程序员最有B格的时候,无非是在小白面前敲着一行又一行的代码(记得换成黑色的背景,不要问为什么,一因为帅就完了),然后使屏幕浮现出炫酷的动画,这才是最有B格的时候,那普通人又看不懂咱的逻辑,对吧~在这里插入图片描述
无论是App还是Web又或者是桌面程序,每一处都有页面间的跳转 ,毕竟一个应用程序都包含多个页面,咱不能一直往下滑吧哈哈

在 Flutter 中,这些元素被称为路由(Route),它们由导航器(Navigator) 控件管理。导航器管理着路由对象的堆栈并提供管理堆栈的方法,如 Navigator.pushNavigator.pop,通过路由对象的进出栈来使用户从一个页面跳转到另一个页面。

详解图:

在这里插入图片描述

Navigator的职责是负责管理Route的,管理方式就是利用一个栈不停压入弹出,当然也可以直接替换其中某一个Route。而Route作为一个管理单元,主要负责创建对应的界面,响应Navigator压入路由和弹出路由。
Flutter定义路由的方式跟前端MVC框架是很相似的,你会看到有这种类似的:/home,/posts,/posts/:id等等,搞前端的同学应该想到熟悉。

本小节内容:

1.普通路由

2.Navigator

​ 1).Navigator.push()

​ 2).Navigator.pop()

3.路由表的管理

4.Navigator.pushNamed()

5.构造方法传值

6.路由传值

7.带数据返回

哎呀妈呀,这一节干货也太多了吧,这要个赞不过分吧,我不要下次一定!!
在这里插入图片描述

1.普通路由

Route:一个页面要想被路由统一管理,必须包装为一个Route

官方的说法很清晰:An abstraction for an entry managed by a Navigator.

但是Route是一个抽象类,所以它是不能实例化的.

2.Navigator

Navigator:是一个路由管理的组件,它提供了打开和退出路由页方法。Navigator通过一个栈来管理活动路由集合。通常当前屏幕显示的页面就是栈顶的路由。

官方解释:A widget that manages a set of child widgets with a stack discipline.

两个路由之间的跳转需要经历下面三个步骤

  1. 创建两个route
  2. Navigate到第二个route使用Navigator.push()
  3. 返回到第一个route使用Navigator.pop()
1).所以,让我们先来创建两个路由

在这里插入图片描述

class FirstRoute extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => FirstState()

}

class FirstState extends State<FirstRoute> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: MaterialButton(
          child: Text("点击跳转到第二个界面"),
          onPressed: () {
            ///处理点击事件
          },
        ),
      ),
    );
  }
}
class FirstRoute extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => FirstState();
}

class FirstState extends State<FirstRoute> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
      	SizedBox(
          height: 320,
        ),
        Center(
          child: MaterialButton(
            child: Text("点击跳转到第一个界面"),
            onPressed: () {
              ///处理点击事件
            },
          ),
        ),
        Center(
          child: MaterialButton(
            child: Text("点击返回到第一个界面"),
            onPressed: () {
              ///处理点击事件
            },
          ),
        ),
      ],
    ));
  }
}
2).使用Navigator.push()来跳转页面

在FirstRoute组件中的onPressed方法中添加我们的Navigator

onPressed: () {
  ///处理点击事件
  Navigator.of(context)
      .push(MaterialPageRoute(builder: (context) => SecondRoute()));
},

注意:Navigator类中第一个参数为context的静态方法都对应一个Navigator的实例方法

Navigator.push(BuildContext context, Route route)
Navigator.of(context).push(Route route)

这两种写法是等价的

3).使用Navigator.pop()来返回上一个页面

我们使用Navigator.pop()来退出SecondRoute并回到FirstRoute,pop()方法回将当前路由从Route栈中移除

在返回按钮中写:

onPressed: () {
  ///处理返回点击事件
  Navigator.pop(context);
},

当然我们也可以在跳转到第一个界面的里面写Navigator.push,不过不推荐这样的写法,因为这样的话没有吧页面从栈中移除。

3.路由表的管理

如果我们的项目中出现了多次跳转到同一个页面的情况,这种方式会造成大量代码的重复,路由表就很好的解决了这个问题。

咋这么多路由呢,感觉在上路由交换的课程哈哈不对劲

定义路由表

在MaterialApp的构造方法中添加两个额外的属性:initialRouteroutes

return MaterialApp(
  title: 'Flutter Route',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
    // 定义APP启动时第一个显示的页面
    initialRoute: '/',
    routes: {
      // 当navigating到‘/’ route时,FirstRoute widget
      '/': (context) => FirstRoute(),
      // 当navigating 到"/second" route, SecondRoute widget.
      '/second': (context) => SecondRoute(),
    },
    ///指定了initialRoute,home就是多余的了
    //home: FirstRoute(),
);

路由表是给每个Route定义了一个名称,这样我们就可以根据这个名称来进行跳转了。

4.Navigator.pushNamed()

通过这个方法跳转时,Flutter会去定义的routes中转到名称所对应的route,并进行跳转。

onPressed: () {
  ///处理点击事件
  ///普通跳转
  // Navigator.of(context)
  //     .push(MaterialPageRoute(builder: (context) => SecondRoute()));
  ///通过路由表跳转
  Navigator.pushNamed(context, "/second");
},

5.构造方法传值

使用于普通跳转,在自定义封装或者写插件时经常会用到。

我们可以在SecondRoute中定义几个参数:

class SecondRoute extends StatefulWidget {
  final int age;
  final String name;

  const SecondRoute({Key key, this.age, this.name}) : super(key: key);

  @override
  State<StatefulWidget> createState() => SecondState();
}

通过构造方法获取参数

这下我们就可以在跳转时传参啦:

Navigator.of(context)
    .push(MaterialPageRoute(builder: (context) => SecondRoute(age: 20,name: "阿T",)));

使用传入的参数:

Text(
    "我的年龄:" + widget.age.toString() + " 我的姓名 " + widget.name)

在这里插入图片描述

6.路由传值

让我们先看看Navigator.pushNamed()的源码:

@optionalTypeArgs
  static Future<T> pushNamed<T extends Object>(
    BuildContext context,
    //路由路径
    String routeName, {
    //携带的参数
    Object arguments,
   }) {
    return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
  }

arguments是跳转携带的参数,它是一个Object,意味着可以传递任意类型的参数。

1)多个数据时准备一个bean
class ScreenArguments {
  final String title;
  final String message;
   ScreenArguments(this.title, this.message);
}
2)跳转界面
Navigator.pushNamed(
      context,
      ExtractArgumentsScreen.routeName,
      arguments: ScreenArguments(
        'title',
        'message',
      )
3)获取参数
 final ScreenArguments args = ModalRoute.of(context).settings.arguments;
4)使用参数
Text(args.title),
 Text(args.message),

7.带数据返回

Navigator.pop(context, '返回的数据');

由于源码中 pop的方法是Object,这里可以传递任意类型参数返回

  @optionalTypeArgs
  static void pop<T extends Object>(BuildContext context, [ T result ]) {
    Navigator.of(context).pop<T>(result);
  }

基础路由就这样简单的实现啦
在这里插入图片描述
欢迎留言纠正 ~ 不妨给个点赞哈哈

我是阿T一个幽默的程序员 我们下期再见~

添加我为你的好友,领取源码以及Flutter学习资料~

在这里插入图片描述

加入我们吧,一起学习,一起进步~

在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程的平行世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值