Flutter路由管理(二)

路由(Route)在移动开发中通常是指页面(Page),这与Web开发的意义是相同的,Route在Andriod中通常指一个Activaty,在IOS中指一个ViewController,路由入栈(push)用于打开一个新页面,路由出栈(pop)操作用于对应页面关闭操作,路由管理则是指如何管理路由栈。

1、示例

  • 创建一个新路由,新页面在页面中间显示一句话
class NewRoute extends StatelessWidget {const NewRoute({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("新页面"),),body: const Center(child: Text("新路由"),),);}
}
  • 在main.dart的_MyHomePageState类中添加以下按钮
ElevatedButton(style: ButtonStyle(foregroundColor:WidgetStateProperty.all(Colors.amberAccent)),onPressed: () {Navigator.push(context, MaterialPageRoute(builder: (context) {return const RouteTestRoute();}));},child: const Text("路由管理")),
1.1 MaterialPageRoute
MaterialPageRoute({required this.builder,super.settings,this.maintainState = true,super.fullscreenDialog,super.allowSnapshotting = true,super.barrierDismissible = false,
})
  • required this.builder:是一个必填的参数,这是一个回调函数,用于构建目标页面的Widget;
  • super.settings:设置对象,用于定义路由的一些元数据,如路由的名字、是否为初始路由等;
  • this.maintainState:入栈新路由时,是否保留在内存的原来路由,设置为false则在路由没用时释放其占用的所有内存;
  • super.fullscreenDialog:表示新的路由是否为一个全屏的模糊对话框,在IOS中,设置为true,则新页面会从屏幕底部划入,而不是在水平方向;
  • super.allowSnapshotting:表示是否允许快照,快照是指当页面不在前台是保留其状态,以便在回到前台是快速恢复;
  • super.barrierDismissible:表示是否可以通过点击页面之外的区域来关闭对话框,对于非全屏的路由,这个属性通常用于控制是否可以点击背景来关闭对话框。
1.2 Navigator
  • 常用方法:
    • push(Route route):向 Navigator 的页面堆栈中添加一个新的页面。这通常用于启动一个新的活动或显示一个对话框;
    • pop([dynamic result]):从 Navigator 的页面堆栈中移除顶部的页面并返回到前一个页面。result 参数是可选的,可以用来传递结果数据给前一个页面;

2、路由传值

2.1 创建TipRoute路由

这个路由的功能是接受一个提示文本参数,并将参数显示在页面上,点击返回按钮后会向上一个页面带上一个返回参数。

class TipRoute extends StatelessWidget {const TipRoute({super.key, required this.text});final String text;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("提示"),),body: Padding(padding: const EdgeInsets.all(18),child: Center(child: Column(children: [Text(text),ElevatedButton(onPressed: () => Navigator.pop(context, "返回值"),child: const Text("返回"),)],),),),);}
}
2.2 RouteTestRoute

返回到该页面时,调试模式下打印上个页面携带的参数

class RouteTestRoute extends StatelessWidget {const RouteTestRoute({super.key});Widget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: const Text("路由传值"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[ElevatedButton(onPressed: () async {// 打开TipRoute,并等待返回结果var result = await Navigator.push(context,MaterialPageRoute(builder: (context) {//路由参数return const TipRoute(text: "提示");}));// 是否为调试模式,是的话为true,不是的话为falseif (kDebugMode) {print("路由返回值:$result");}},child: const Text("打开提示页")),// ElevatedButton(//   onPressed: () {//     Navigator.push(context, MaterialPageRoute(builder: (context) {//       return const MyHomePage(title: "主页");//     }));//   },//   child: const Text("返回主页"),// )])));}
}

3、路由命名

我们可以通过给路由起一个名字,通过这个名字直接打开路由,这使得路由管理更加直观、简单。

3.1 路由表

使用命名路由的前提是提供并注册一个路由表,为名字与路由组件提供对应关系,注册路由表的过程就是为路由起一个名字

  • 定义:Map<String, WidgetBuilder> routes;

它是一个Map,Key为路由的名字,是一个字符串;

value是builder回调函数,用于生成对应路由的Widget;

应用会根据路由名字在路由表中查到对应的WidgetBuilder回调函数,然后调用该回调函数生成Widget并返回。

3.2 注册路由表

使用inititalRoute设置初始路由,并使用后routes注册路由表。更改后要热重载一下,避免页面报错。

class MyApp extends StatelessWidget {/* 声明了一个常量构造函数,它使得Flutter在编译时就确定MyApp对象的结构,而不是在运行时动态创建。这可以提升一定性能,在编译时优化常量对象的创建过程,并且在多个地方使用同一个常量对象时可以减少内存使用。*/const MyApp({super.key});Widget build(BuildContext context) {return MaterialApp(// 应用名称title: 'Flutter Demo',initialRoute: "/",  // 初始路由// 主题设置theme: ThemeData(// 主题颜色colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),// 是否使用Material 3的设计规范useMaterial3: true,),// 注册路由表routes: {"/": (context) => const MyHomePage(title: 'Flutter Demo Home Page'),  // 主页路由"new_page": (context) => const NewRoute(),  // 新路由},// 应用首页路由// home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}
3.3 通过路由名打开新页面

通过路由名打开新路由有两种方式:

  • Navigator.pushNamed:它是最常用的导航发生它允许通过指定的名称打开一个新页面,适合在已经注册名称的情况下使用;
  • Navigator.pushNamedAndRemoveUntil:除了导航到指定的路由外,还会移除直到目标路由的所有页面,非常适合导航到新页面时清除所有中间的页面历史,比如登录后的主页面导航。
// 示例
ElevatedButton(style: ButtonStyle(foregroundColor: WidgetStateProperty.all(Colors.cyan)),onPressed: () {Navigator.pushNamed(context, "new_page");// Navigator.push(context, MaterialPageRoute(builder: (context) {//   return const NewRoute();// }));},child: const Text("示例路由")),

更改示例路由的跳转方式,点击热重载,点击示例路由发现依然可以跳转新路由界面。

3.4 命名路由参数传递
3.4.1 传递参数

修改按钮点击的回调函数,在通过名字访问路由时传递一个arguments值。

ElevatedButton(style: ButtonStyle(foregroundColor: WidgetStateProperty.all(Colors.cyan)),onPressed: () {// 直接打开路由// Navigator.pushNamed(context, "new_page");// 打开路由时传递参数Navigator.of(context).pushNamed("new_page", arguments: "路由参数");// Navigator.push(context, MaterialPageRoute(builder: (context) {//   return const NewRoute();// }));},child: const Text("示例路由")),
3.4.2 接收参数

在名字对应的路由中接收参数并将参数打印在控制台上。

// 新路由示例
class NewRoute extends StatelessWidget {const NewRoute({super.key});Widget build(BuildContext context) {// 获取路由参数var args = ModalRoute.of(context)?.settings.arguments;if (kDebugMode) {print(args);}return Scaffold(appBar: AppBar(title: const Text("新页面"),),body: const Center(child: Text("新路由"),),);}
}
3.4.3 适配

在TipRoute类中,我们通过Navigator.pop(context, “返回值”)将参数传递给上一个页面,在不改变TipRoute源码的情况下适配并将该路由命名。

Widget build(BuildContext context) {return MaterialApp(// 省略无关代码...// 提示页路由"tip2": (context){// 获取传递的参数final arguments  = ModalRoute.of(context)?.settings.arguments;final text = arguments is String ? arguments : '默认文本';return TipRoute(text: text);},},// 应用首页路由// home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}

RouteTestRoute类直接修改按钮回调函数返回默认文本。

class RouteTestRoute extends StatelessWidget {const RouteTestRoute({super.key});Widget build(BuildContext context) {// 省略无关代码...ElevatedButton(onPressed: () async {Navigator.of(context).pushNamed("tip2");},

若页面接收传递参数,则显示传递参数。

// 新路由示例
class NewRoute extends StatelessWidget {// 省略无关代码...return Scaffold(appBar: AppBar(title: const Text("新页面"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[ElevatedButton(onPressed: () {Navigator.of(context).pushNamed("tip2", arguments: args);},child: const Text("新路由"))],)),);}
}
3.5 路由生成钩子

假如我们要判断用户是否登录,每打开一个路由页都进行一次判断很麻烦,当Navigator.pushNamed打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果没有注册,则会调用onGenerateRoute来生成路由,回调签名如为:Route< dynamic > onGenerateRoute(RouteSettings settings),有了onGenerateRoute回调,就可以十分容易的控制页面权限了,我们不使用路由表,而是提供一个onGenerateRoute回调,在该回调中进行统一的权限控制。

  // // 注册路由表// routes: {//   // 主页路由//   "/": (context) => const MyHomePage(title: 'Flutter Demo Home Page'),//   // 新路由//   "new_page": (context) => const NewRoute(),//   // 提示页路由//   "tip2": (context) {//     // 获取传递的参数//     final arguments = ModalRoute.of(context)?.settings.arguments;//     final text = arguments is String ? arguments : '默认文本';//     return TipRoute(text: text);//   },// },// 使用onGenerateRoute管理路由onGenerateRoute: (RouteSettings settings) {return MaterialPageRoute(builder: (context) {if (settings.name == "/") {return const MyHomePage(title: 'Flutter Demo Home Page');} else if (settings.name == "new_page") {return const NewRoute();} else if (settings.name == "tip2") {// 获取传递的参数final arguments = ModalRoute.of(context)?.settings.arguments;final text = arguments is String ? arguments : '默认文本';return TipRoute(text: text);}// 如果没有匹配路由则返回默认页面return const MyHomePage(title: 'Flutter Demo Home Page');});},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/881791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原生小程序开发组件|地图组件汇总

map 基础库 2.0.12 开始支持, 低版本需做兼容处理。 依赖 MapKit 插件, 插件版本 > 2.2.2。 Tuya MiniApp Tools 上是通过 WebView 模拟的与真机存在差异&#xff0c;请以真机效果为主。 地图。相关 API&#xff1a;ty.createMapContext。这是基于异层渲染的原生组件, 请注意…

el-date-picker 自定义指令,输入数字自动转换显示yyyy-mm-dd格式

el-date-picker 自定义指令&#xff0c;输入数字显示yyyy-mm-dd格式 在main.js引入自定义指令direct.jsdirect.js公共部分时间日期控件&#xff0c;表格内编辑时间控件可用 - (年-月-日)时间范围控件 - (年-月-日)日期转换主要正则年-月-日/年-月-日 时:分/年-月-日 时:分:秒年…

Element-plus el-form、el-dialog 数据回显同时用时,重置失效问题

问题 当第一次打开网页并点击“编辑”按钮时&#xff0c;虽然对话框变量变为 true 使对话框可见&#xff0c;但同步代码会将 formData 对象的属性设置为默认值。由于 Vue 的异步更新机制&#xff0c;DOM 实际上还未更新&#xff0c;因此表单组件内绑定了这些有值的初始数据。这…

【病毒分析】DevicData家族扩散:全球企业和机构成为勒索病毒头号攻击目标!

1.背景 本文聚焦于勒索病毒家族 DevicData 的最新变种&#xff0c;命名为 .DevicData-P a2a9e9c勒索病毒。自2023年1月首次被发现以来&#xff0c;DevicData 家族一直对多个高价值目标展开攻击&#xff0c;包括企业用户、医疗机构和教育机构。这些目标通常持有大量敏感数据&a…

初始爬虫13(js逆向)

为了解决网页端的动态加载&#xff0c;加密设置等&#xff0c;所以需要js逆向操作。 JavaScript逆向可以分为三大部分&#xff1a;寻找入口&#xff0c;调试分析和模拟执行。 1.chrome在爬虫中的作用 1.1preserve log的使用 默认情况下&#xff0c;页面发生跳转之后&#xf…

已发布金融行业标准目录(截止2024年3月)

已发布金融行业标准目录2024年3月序号行业标准编号标准名称

MySQL学习(五):数据类型与约束

MySQL学习&#xff08;五&#xff09;&#xff1a;数据类型与约束 文章目录 MySQL学习&#xff08;五&#xff09;&#xff1a;数据类型与约束1. 数据类型与属性1.1 所有的数据类型1.2 所有属性 2. 数据类型详解2.1 整型2.2 浮点类型2.3 定点数类型2.4 位类型2.5 日期与时间2.6…

Linux环境基础开发工具的使用

vim编辑器的基本操作: 在linux环境下输入vim 文件名就可以进入编辑模式. 上述四种模式必须退到命令模式才能进行下一个模式. 在编辑器中写完之后,输入ESC进入命令模式,然后再输入shift:进入低行模式并输入wq保存并退出. 在命令模式下的操作: 光标所在行:1.输入yy进行复制, 输…

golang语法

参考链接&#xff1a;https://www.runoob.com/go/ 创建变量 // 3种方法 var a int a : 10 // 类型推断 a : make() // 复合类型循环 // 3种循环 for i : 0; i < 10; i {// 循环体} // 传统for循环 for index, num : range nums {// 循环体} // nums是可迭代的复合类型…

ubuntu24 root用户修改密码 ubuntu新系统没有创建root用户

ubuntu 系统在虚拟机新建一个ubuntu24&#xff0c;但是在配置系统时候&#xff0c;并没有配置root密码&#xff0c;只是新增了一个自定义账号于密码&#xff0c;在创建好后&#xff0c;可以登录系统&#xff0c;设置root密码~ 1. ubuntu系统初始化后&#xff0c;登录自建账号 …

k8s介绍-搭建k8s

Kubernetes介绍&#xff0c;官网&#xff1a;Kubernetes 应用部署方式演变 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其他技术的参与 缺点&#xff1a;不能为应用程序定义资源使用边界&#xff0c…

【C++网络编程】(一)Linux平台下TCP客户/服务端程序

文章目录 Linux平台下TCP客户/服务端程序服务端客户端相关头文件介绍 Linux平台下TCP客户/服务端程序 图片来源&#xff1a;https://subingwen.cn/linux/socket/ 下面实现一个Linux平台下TCP客户/服务端程序&#xff1a;客户端向服务器发送&#xff1a;“你好&#xff0c;服务…

从零创建苹果App应用,不知道怎么申请证书的可以先去看我的上一篇文章

用大家自己的开发者账户&#xff0c;登录进入App Store Connect ,注册自己的应用 进入之后&#xff0c;点击增加 填写相关的信息 一切顺利的话&#xff0c;就可以来到这个页面

得了自闭症怎么办

当孩子被诊断为自闭症时&#xff0c;家长们往往会感到迷茫、无助和焦虑。然而&#xff0c;自闭症并不是无法逾越的障碍&#xff0c;通过科学的干预和支持&#xff0c;自闭症儿童可以取得显著的进步&#xff0c;过上有质量的生活。在这个过程中&#xff0c;专业的机构如星贝育园…

取消apply_async调度的任务

在 Celery 中&#xff0c;使用 apply_async 方法调度的任务可以通过任务 ID 来取消。以下是如何取消 apply_async 调度的任务的详细步骤&#xff1a; 1. 获取任务 ID 当你使用 apply_async 方法调度任务时&#xff0c;它会返回一个 AsyncResult 对象&#xff0c;该对象包含任…

C++ 面向对象、特征、重载和重写、构造和析构、向上和向下转型、深浅拷贝。

什么是面向对象&#xff08;Object-Oriented Programming, OOP&#xff09; 1.面向对象是一种编程范式&#xff0c;它通过将软件系统的设计和开发分解为“对象”&#xff08;Object&#xff09;的方式来实现更好地组织代码。面向对象的核心思想是将程序的结构分为对象&#xf…

element plus的el-select分页

摘要&#xff1a; el-select的数据比较多的时候&#xff0c;必须要分页&#xff0c;处理方案有全部数据回来&#xff0c;或者添加搜索功能&#xff0c;但是就有个问题就是编辑的时候回显问题&#xff0c;必须要保证select的数据有对应的id与name匹配回显&#xff01; <el-fo…

计算机网络-VRRP实验配置

前面我们大致学习了VRRP的概念和基本原理&#xff0c;但是网络这块就是要多敲命令多用才能印象深刻&#xff0c;今天开始进行一些实验配置&#xff0c;结合日常工作的场景分析VRRP在实际工作中的应用。 一、典型VRRP虚拟网关拓扑 相比于传统单网关&#xff0c;采用VRRP虚拟网关…

Qt/C++编写的mqtt调试助手使用说明

一、使用说明 第一步&#xff0c;选择协议前缀&#xff0c;可选mqtt://、mqtts://、ws://、wss://四种&#xff0c;带s结尾的是走ssl通信&#xff0c;ws表示走websocket通信。一般选默认的mqtt://就好。第二步&#xff0c;填写服务所在主机地址&#xff0c;可以是IP地址也可以…

2024.10月11日--- SpringMVC拦截器

拦截器 1 回顾过滤器&#xff1a; Servlet规范中的三大接口&#xff1a;Servlet接口&#xff0c;Filter接口、Listener接口。 过滤器接口&#xff0c;是Servlet2.3版本以来&#xff0c;定义的一种小型的&#xff0c;可插拔的Web组件&#xff0c;可以用来拦截和处理Servlet容…