Flutter 路由管理

Flutter 路由管理

概述

  • 路由在移动开发中通常指页面,在Android中通常指代一个Activity。Flutter中的路由管理与原生开发较类似,路由管理指页面跳转关系。
  • 路由入栈(push)操作对应打开一个新页面,出栈(pop)操作对应关闭页面。

简单路由

  • 入栈,即新开一个页面,需要调用Future<T?> push<T extends Object?>(BuildContext context, Route<T> route)
  • 出栈,即关闭页面,需要调用pop<T extends Object?>(BuildContext context, [ T? result ])
  • Navigator:这是一个组件,用于管理和维护一个基于栈堆的历史记录,通过pushpop进行页面的跳转。

入栈

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => NewPage()),
);

出栈

Navigator.pop(context);

maybePop()

maybePop方法只会在路由堆栈有可弹路由时才会出栈。

Navigator.maybePop(context);

canPop()

canPop方法可以判断当前路由堆栈是否可以出栈。

if (Navigator.canPop(context)) {
    Navigator.pop(context);
}

pushReplacement()

pushReplacement方法可以用于切换路由页面。

Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => NewPage()),
);

pushAndRemoveUntil()

进入新页面并之前所有页面。

Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) {
    return FourthPage();
}), (route) => false);

命名路由

命名路由指有名字的路由,通过给路由起名字,通过路由名直接打开新的页面,便于路由管理。

  • pushNamed是命名路由的方式。
  • 需要在MaterialApp中配置路由名称。

注册路由表

使用命名路由,必须先注册一个路由表,在MyApp类中添加routes属性。

方式一

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(   
            routes: {
                "/NewPage": (context) {
                    return NewPage();
                },
            },
            home: MyHomePage(title: '首页标题'),
        );
    }
}

方式二

首页home路由使用命名路由,需要在routes中注册MyHomePage路由,然后在initialRoute声明初始路由。

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(    
            routes: {
                "/": (context) {
                    return MyHomePage(title: '首页标题');
                },
                "NewPage": (context) {
                    return NewPage();
                },
            },
            initialRoute: "/",
        );
    }
}

入栈

Navigator.pushNamed(context, "/first_page");

pushReplacementNamed()

pushReplacementNamed方法可以用于切换路由页面,退出当前页面,并切换至新页面。

Navigator.pushReplacementNamed(context, "/second_page");

popAndPushNamed()

popAndPushNamed方法与pushReplacementNamed方法的功能基本一致,唯一的区别是会有页面退出的动画。

Navigator.popAndPushNamed(context, "/second_page");

pushNamedAndRemoveUntil

进入新页面,并删除路由栈堆直到/first_page页面,当新页面退出时,会显示/first_page页面。

Navigator.pushNamedAndRemoveUntil(context, "/fourth_page", ModalRoute.withName('/first_page'));

popUntil()

出栈到指定页面。

Navigator.popUntil(context, ModalRoute.withName('/first_page'));

传递参数

构造函数方式

第一个页面

//跳转
Navigator.push(
    context,
    MaterialPageRoute(builder: (context) {
        return SecondPage("hello world");
    }),
);

第二个页面

class SecondPage extends StatelessWidget {
    String title;

    SecondPage(this.title);

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text(title),
            ),
        );
    }
}

命名路由传参

  • 使用arguments传递参数。
  • 使用 ModalRoute.of(context)!.settings.arguments获取参数。

第一个页面

Navigator.pushNamed(context, "/second_page", arguments: {"name": "小明", "age": 18, "address": "beijing"});

第二个页面

class SecondPage extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        var arguments = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>?;
        print(arguments);

        return Scaffold(
            appBar: AppBar(
                title: Text("第二个页面"),
            ),
            body: Text("姓名:${arguments!["name"]} 年龄:${arguments["age"]} 地址:${arguments["address"]} "),
        );
    }
}

普通路由传参

第一个页面

Navigator.push(
    context,
    MaterialPageRoute(
        builder: (context) {
            return SecondPage();
        },
        settings: const RouteSettings(
            name: "params",
            arguments: {"name": "小明", "age": 18, "address": "beijing"},
        ),
    ),
);

第二个页面

var route = ModalRoute.of(context);
Map<String, dynamic>? _arguments;
if (route != null) {
  _arguments = route.settings.arguments as Map<String, dynamic>?;
}

返回参数

push相关方法返回Future类型,可以使用await等待返回结果。

async-await方式

第二个页面

Navigator.pop(context, "hello 返回");

第一个页面

onPressed: () async {
    var result = await Navigator.pushNamed(context, "/second_page");
    print(result);
},

then

Navigator.pushNamed(context, "/second_page")
    .then((value) => {print(value)});

路由钩子

在使用命名路由跳转时,如果路由注册表没有注册,这时会调用onGenerateRoute回调。

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '任务栏标题',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
        "/": (context) {
          return const MyHomePage(title: '首页标题');
        },
      },
      initialRoute: "/",
      onGenerateRoute: (RouteSettings settings) {
        print("onGenerateRoute ${settings.name}");
        if (settings.name == "NewPage") {
          return MaterialPageRoute(builder: (context) {
            return NewPage();
          });
        }
      },
    );
  }
}

总结

推荐使用命名路由,理由如下:

  1. 语义化描述更清晰。
  2. 方便代码维护。
  3. 可以使用onGenerateRoute回调。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值