Flutter 教程(六)路由管理

在 Flutter 中,路由管理和Android、iOS类似,都是用于管理界面之间的跳转。在 flutter 中,我们使用 Navigator 来实现跳转的功能

界面跳转

在 flutter 中,支持两种跳转方式,一种是直接跳转,一种是通过路由表跳转。下面分别介绍:

直接跳转

我们可以使用 Navigator.push 方法直接跳转到新的界面,还可以使用 Navigator.pop 回退到之前的界面。代码示例如下:

less 复制代码
Navigator.push(context, MaterialPageRoute(builder: (context) {
  return NewRoute();
}));

其中MaterialPageRoute 是 Material组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

路由表跳转

要实现路由表跳转,我们需要先在 MaterialApp 的 routes 中注册,代码示例如下:

scala 复制代码
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // 注册路由表
      routes: {
        'newRoute': (context) => NewRoute(),
      },
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

然后通过 Navigator.pushNamed 方法来跳转界面,代码示例如下:

arduino 复制代码
Navigator.pushNamed(context, 'newRoute');

界面之间传递参数

界面A传递数据到界面B

  • 直接跳转

对于直接跳转的情况,我们把数据传入就可以了,代码示例如下:

scala 复制代码
class NewRoute extends StatelessWidget {
  
  // 增加标题数据
  final String title;

  NewRoute({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("New route $title"),
      ),
      body: Center(
        child: Text("This is new route"),
      ),
    );
  }
}


Navigator.push(context, MaterialPageRoute(builder: (context) {
  // 设置对应的数据
  return NewRoute(title: "新的标题",);
}));
  • 路由表跳转

对于路由表跳转,我们需要通过 ModalRoute.of(context)!.settings.arguments 来接收参数,代码示例如下:

scala 复制代码
class NewRoute extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // 接收参数
    final args = ModalRoute.of(context)!.settings.arguments as Map<String, String>;
    final message = args['message'];
    return Scaffold(
      appBar: AppBar(
        title: Text("New route $message"),
      ),
      body: Center(
        child: Text("This is new route"),
      ),
    );
  }
}

Navigator.pushNamed(context, 'newRoute', arguments: {"title": "新的标题"});

界面B返回数据给界面A

scala 复制代码
// 设置返回值
Navigator.pop(context, "我是返回值")

class RouterTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () async {
          // 打开`TipRoute`,并等待返回结果
          var result = await Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) {
                return TipRoute(
                  // 路由参数
                  text: "我是提示xxxx",
                );
              },
            ),
          );
          //输出`TipRoute`路由返回结果
          print("路由返回值: $result");
        },
        child: Text("打开提示页"),
      ),
    );
  }
}

首页

默认情况下,MaterialApp 中的 home 属性用来设置首页的界面。

scala 复制代码
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

如果你想让首页也支持路由表跳转,需要使用 initialRoute 属性,代码示例如下:

less 复制代码
MaterialApp(
  title: 'Flutter Demo',
  initialRoute:"/", //名为"/"的路由作为应用的home(首页)
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
   "/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
  } 
);

其他路由方法

Navigator 除了基础的pushpop方法外,还提供了其他的方法,如下表所示:

方法名 介绍 路由关系示例 参数传递与接收
pushReplacementNamed(BuildContext context, String routeName, {Object arguments}) 使用注册的路由命名替换当前路由,从当前页面跳转到新页面,栈顶路由被替换。类似pushReplacement,只是使用路由命名而非直接路由。 当前路由顺序为A-B-C,从C执行pushReplacementNamed到D(假设D已注册路由名为"paged"),路由顺序变为A-B-D。若在D页面执行pop,路由顺序变为A-B 通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。由于原页面已被替换,无法接收原页面返回值
popAndPushNamed<T extends Object, TO extends Object>(BuildContext context, String routeName, {TO result, Object arguments}) 当前路由出栈,同时栈顶入栈一个新路由(通过注册的路由名指定)。 当前路由顺序为A-B-C,在C页面执行popAndPushNamed到D(假设D已注册路由名为"paged"),路由顺序变为A-B-D 可通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。result参数用于在出栈时向原页面传递数据(若有需要)
pushReplacement(BuildContext context, Route route, {TO result}) 用新路由替换当前路由,跳转到新页面,原页面被移除。 当前路由顺序为A-B-C,从C执行pushReplacement到D,路由顺序变为A-B-D。若在D页面执行pop,路由顺序变为A-B 通过目标页面的构造方法传递参数。由于原页面已被替换,无法接收原页面返回值
pushNamedAndRemoveUntil(BuildContext context, String routeName, RoutePredicate predicate, {Object arguments}) 跳转到注册路由名对应的新页面,并根据predicate的返回值决定新路由之前的路由的处理方式。类似pushAndRemoveUntil,只是使用路由命名而非直接路由。 1. 若predicate返回false,当前路由顺序为A-B-C-D-E,从E执行pushNamedAndRemoveUntil到F(假设F已注册路由名为"paged"),路由顺序变为F,A-E全部出栈。 2. 若predicate返回true,路由顺序变为A-B-C-D-E-F。 3. 若predicateModalRoute.withName指定的命名路由名称(如"pagea"),假设当前路由顺序为T-A-B-C-D,从C执行pushNamedAndRemoveUntil到D(假设D已注册路由名为"paged"),路由顺序变为T-A-D 通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。由于原页面部分或全部被移除,无法接收原页面返回值
popUntil(BuildContext context, RoutePredicate predicate) 从栈顶开始逐个出栈路由,直到满足predicate指定的条件(条件可以是注册的路由名或RouteSetting设置的名称)。 当前路由顺序为A-B-C-D-E,在E页面执行popUntil(context, ModalRoute.withName('B')),路由顺序变为A-B 在出栈过程中,若需要传递数据给前一个页面(在满足条件停止出栈前的页面),可结合其他机制(如在相关页面的状态管理中处理)

fluro

前文介绍的所有路由知识都是Flutter官方提供的基本知识。在实际的Flutter项目中,开发人员往往并不这么写,因为还有一种更为方便的操作,也就是使用Flutter提供给我们的第三方路由库------fluro

关于 fluro 的使用,具体可以看 初识 fluro 路由管理

参考

相关推荐
小墙程序员5 小时前
Flutter 教程(十)主题
flutter
小墙程序员6 小时前
Flutter 教程(九)权限
flutter
pengyu7 小时前
系统化掌握Dart网络编程之Dio(二):责任链模式篇
android·flutter·dart
侑柚酒8 小时前
一个例子直观的告诉你flutter中key的作用
flutter
pengyu9 小时前
系统化掌握Dart网络编程之Dio(二):配置管理篇
android·flutter·dart
蹲街式等待11 小时前
Flutter dart代码混淆与解混淆
flutter
唔6614 小时前
flutter 曲线学习 使用第三方插件实现左右滑动
javascript·学习·flutter
harry235day15 小时前
Flutter getx 状态管理
flutter·前端框架
小墙程序员16 小时前
Flutter 教程(八)数据存储
flutter
pengyu16 小时前
系统化掌握Dart网络编程之Dio(一):筑基篇
android·flutter·dart