Flutter 路由管理

文章目录

  • Flutter 路由管理
    • 概述
    • 简单路由
      • 入栈
      • 出栈
      • maybePop()
      • canPop()
      • pushReplacement()
      • pushAndRemoveUntil()
    • 命名路由
      • 注册路由表
      • 入栈
      • pushReplacementNamed()
      • popAndPushNamed()
      • pushNamedAndRemoveUntil
      • popUntil()
    • 传递参数
      • 构造函数方式
      • 命名路由传参
      • 普通路由传参
    • 返回参数
      • async-await方式
      • then
    • 路由钩子
    • 总结

Flutter 路由管理

概述

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

简单路由

  • 入栈,即新开一个页面,需要调用Future push(BuildContext context, Route route)
  • 出栈,即关闭页面,需要调用pop(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?;
        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? _arguments;
if (route != null) {
  _arguments = route.settings.arguments as Map?;
}

返回参数

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回调。

你可能感兴趣的:(Flutter,Flutter路由管理)