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 除了基础的push和pop方法外,还提供了其他的方法,如下表所示:

方法名 介绍 路由关系示例 参数传递与接收
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. 若predicate为ModalRoute.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 路由管理

参考

相关推荐
大龄秃头程序员1 小时前
Flutter 最少代码验证:为什么子 Isolate 调原生,一定要先回到主 Isolate?
flutter
FungLeo2 小时前
成为全栈·Flutter App 篇·分类、标签与搜索:移动端内容发现
flutter·移动开发·标签·搜索·分类管理·成为全栈
m0_738185823 小时前
Flutter 鸿蒙化实战:the_apple_sign_in 适配 OpenHarmony,Apple 登录
flutter·华为·harmonyos·鸿蒙
m0_738185824 小时前
Flutter 鸿蒙化实战:umeng_analytics_plugin 适配 OpenHarmony,友盟统计
flutter·华为·harmonyos·鸿蒙
FungLeo5 小时前
成为全栈·Flutter App 篇·列表分页与下拉刷新:去重、失败保留和返回位置
flutter·移动开发·下拉刷新·分页加载·列表优化·成为全栈
大龄秃头程序员7 小时前
【从一道面试题入手】深入理解 Dart 事件循环调度机制
flutter
恋猫de小郭8 小时前
Kotlin 2.5 的 Companion 改造,对 KMP 的重要升级
android·前端·flutter
程序员老刘1 天前
Flutter你看看人家RN
flutter·react native·ai编程
大龄秃头程序员1 天前
【Flutter Bloc 从 0 到 1】用最少代码跑通 Bloc
flutter
m0_738185821 天前
Flutter 鸿蒙化实战:sqflite 适配 OpenHarmony,本地 SQLite 数据库
flutter·华为·harmonyos·鸿蒙