美文网首页Flutter
[Flutter] Navigator的使用记录

[Flutter] Navigator的使用记录

作者: 沉江小鱼 | 来源:发表于2021-06-05 20:30 被阅读0次

    1. 简单的路由使用:

    // 跳转到一个新的页面
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
          return HomePage();
    }));
    

    MaterialPageRoute 继承自PageRoute(抽象类),MaterialPageRouteMaterial组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

    构造函数:

      MaterialPageRoute({
         // 构建路由页面,返回一个widget
        WidgetBuilder builder,
        // 包含路由的配置信息,如路由名称、是否初始路由(首页)
        RouteSettings settings, 
        // 默认情况下,入栈一个新路由时,原来的路由一直保存,如果想在路由没用的时候(??)释放其资源,设置maintainState为false
        bool maintainState = true,
        // 表示新的路由页面是否是一个全屏的模态对话框,ios中如果为true,说明是模态跳转
        bool fullscreenDialog = false,
      })
    

    可以继承PageRoute来实现自定义路由切换动画。

    2. Navigator

    使用栈管理路由。

    2.1 基础用法:打开&关闭
    // 打开新的页面,返回一个Future对象,接收新路由出栈(关闭)时的返回数据
    Future push(BuildContext context, Route route)
    
    // 关闭页面,result为返回参数
    bool pop(BuildContext context, [ result ])
    
    

    Navigator类中第一个参数为context的静态方法都对应一个实例方法,比如:Navigator.push(BuildContext context, Route route) 等价于 Navigator.of(context).push(Route route)

    2.2 逆向传值

    场景:A页面中打开B页面,B页面关闭时给A传值。

    代码如下:

    A页面跳转代码:
    // 返回的是一个Future对象
    Future future = Navigator.of(context).push(
          MaterialPageRoute(
              builder: (context) {
                return HomePage();
              },
              maintainState: false),
        );
    // 获取回调过来的数据
    future.then((value) {
          print(value);
    });
    
    B页面代码:
    // 关闭页面
    Navigator.of(context).pop("这是回调给A页面的数据");
    
    2.3 命名路由

    就是给路由起个名字,然后使用名字打开路由,更简单方便。

    2.3.1 路由表

    维护路由和名字的映射关系,就需要用到路由表

    // value 是一个builder回调函数,用于生成相应的路由widget
    Map<String, WidgetBuilder> routes;
    

    通过路由名字打开路由时,会从路由表中查找对应的WidgetBuilder回调函数,然后调用该回调函数生成路由Widget并返回。

    2.3.2 路由表注册

    main.dart文件中的MaterialApp构造函数中,添加routes(注册路由表)和initialRoute(标明应用的首页):

    MaterialApp(
      title: 'FlutterStudy',
      initialRoute:"/", //名为"/"的路由作为应用的home(首页)
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      //注册路由表
      routes:{
       "login_page": (context) => LoginPage(),
       "/":(context) => HomePage(), //注册首页路由
      } ,
    );
    

    如果使用了initialRoute指定应用首页,那么MaterialApp就不能使用home属性指定首页了,会有冲突。

    2.3.3 命名路由简单使用

    命名路由和普通路由的方法不同在于方法名字多了一个 named以及参数不同,很好区分,比如下面的方法:

    • 通过路由名打开新路由
    Future pushNamed(BuildContext context, String routeName,{Object arguments})
    

    示例:

    // 通过路由名字打开路由,并传递参数
    Navigator.of(context)
                  .pushNamed("login_page", arguments: {"id": "111"});
    
    // 接收参数
    routes: {
        "/": (context) => HomePage(),
        "login_page": (context) {
        // 获取参数
        Map args = ModalRoute.of(context).settings.arguments;
              print(args);
              return LoginPage(id: args['id']);
            }
        },
    }
    
    2.3.4 路由生成钩子

    使用场景:APP中打开某些功能需要判断是否登录,通过路由生成钩子可以统一进行处理。

    MaterialApp有一个onGenerateRoute属性,当通过Navigator.pushName()打开路由时:

    • 如果指定的路由名已经在路由表中注册了,就会调用路由表中的builder函数生成路由组件;
    • 如果没有注册,会调用onGenerateRoute来生成路由;

    onGenerateRoute 只会对命名路由生效。

    回调签名:

    Route<dynamic> Function(RouteSettings settings)
    

    可以不使用路由表,只使用onGenerateRoute回调,然后在该回调中进行统一的权限控制:

    MaterialApp(
      ... //省略无关代码
      onGenerateRoute:(RouteSettings settings){
          return MaterialPageRoute(builder: (context){
               String routeName = settings.name;
           // 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
           // 引导用户登录;其它情况则正常打开路由。
         }
       );
      }
    );
    

    3. Navigator相关方法记录

    3.1 常用跳转方法:
    // 弹出当前页面,并跳转到一个新的页面
    // A->B->C->D ,D页面调用后,A->B->C->B
    Navigator.popAndPushNamed(context, 'B');
    
    // 弹出栈中的页面,直到指定的页面
    // A->B->C->D ,D页面调用后,A->B
    Navigator.popUntil(context, ModalRoute.withName("B"));
    
    // 弹出栈中的页面,直到指定的页面,然后跳转一个新页面
    // A->B->C->D ,D页面调用后,A->B->F
    Navigator.pushAndRemoveUntil(
                  context,
                  MaterialPageRoute(
                      builder: (BuildContext context) => new F()),
                  ModalRoute.withName("B"));
    
    // 和上面一样,只不过是跳转命名路由
    // A->B->C->D ,D页面调用后,A->B->F
    Navigator.pushNameAndRemoveUntil(
                  context,
                  "F"
                  ModalRoute.withName("B"));
    
    // 和上面一样,只不过是跳转命名路由
    // A->B->C ,D页面调用后,A->B->D
    Navigator.pushReplacementNamed(context, "D");
    Navigator.pushReplacement(context, MaterialPageRoute(
                      builder: (BuildContext context) => new D()));
    
    
    3.2 其他方法:
    // 判断是否可以导航到新页面
    canPop 
    // 可能会导航到新页面
    maybePop 
    // 从Navigator中删除路由,同时执行Route.dispose操作。
    removeRoute 
    // 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
    removeRouteBelow 
    // 将Navigator中的路由替换成一个新路由。
    replace 
    // 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由
    replaceRouteBelow 
    

    项目中使用时可以自己封装一下路由管理类,也可以使用 Fluro。本篇文章只是记录 Navigator 的一些用法,更详细的可以参考:Flutter实战:路由管理

    相关文章

      网友评论

        本文标题:[Flutter] Navigator的使用记录

        本文链接:https://www.haomeiwen.com/subject/pdtcsltx.html