Flutter笔记:路由观察者
作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134572181
目 录
1. 概述
路由观察者(Route Observer)是一个监听路由(页面)变化的工具。在Flutter应用中,我们经常需要监听路由的变化,例如当用户从一个页面跳转到另一个页面时,我们可能需要执行一些操作,如数据统计、页面切换动画等,这时就需要用到路由观察者。
路由观察者的定义:路由观察者是一个抽象类,它定义了一些方法,这些方法可以在路由发生变化时被调用。我们可以通过继承路由观察者类并实现这些方法,来创建自己的路由观察者。
路由观察者的作用:路由观察者的主要作用是监听路由的变化,当路由发生变化时,路由观察者的相应方法会被调用,我们可以在这些方法中执行需要的操作。
路由观察者的使用场景:路由观察者可以用于各种需要监听路由变化的场景,例如数据统计、页面切换动画、用户行为跟踪等。
总的来说,路由观察者是Flutter中一个非常重要的工具,它可以帮助我们更好地理解和控制路由的变化。
2. 路由观察者的创建和使用
2.1 NavigatorObserver类的介绍
在Flutter中,路由观察者是通过继承NavigatorObserver类来创建的。NavigatorObserver是一个抽象类,它定义了一些方法,这些方法会在路由发生变化时被调用。例如,didPush方法会在新的路由被推送到导航器时被调用,didPop方法会在路由从导航器中弹出时被调用。
2.2 创建一个NavigatorObserver的子类
要创建一个路由观察者,我们需要创建一个NavigatorObserver 的子类,并实现它的方法。下面是一个简单的例子:
class MyRouteObserver extends NavigatorObserver {void didPush(Route route, Route previousRoute) {super.didPush(route, previousRoute);print('didPush ${route.settings.name}');}void didPop(Route route, Route previousRoute) {super.didPop(route, previousRoute);print('didPop ${route.settings.name}');}
}
在这个例子中,我们创建了一个名为 MyRouteObserver 的路由观察者,它会在路由被推送和弹出时打印路由的名称。
2.3 将路由观察者添加到MaterialApp或WidgetsApp
创建了路由观察者后,我们需要将它添加到 MaterialApp 或 WidgetsApp 中,这样它才能监听到路由的变化。这可以通过设置navigatorObservers 属性来实现:
void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {final MyRouteObserver _myRouteObserver = MyRouteObserver();Widget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',navigatorObservers: [_myRouteObserver],home: MyHomePage(),);}
}
在这个例子中,我们创建了一个 MyRouteObserver 的实例,并将它添加到了 MaterialApp 的navigatorObservers中。这样,MyRouteObserver 就能监听到所有路由的变化了。
3. 路由观察者的方法
路由观察者的方法主要包括 didPush,didPop,didRemove 和 didReplace 等。下面我们来详细介绍这些方法。
3.1 didPush
didPush 方法会在新的路由被推送到导航器时被调用。它有两个参数:route 和 previousRoute,分别表示新推送的路由和之前的路由。
使用场景:当我们需要在新的路由被推送时执行一些操作时,可以在didPush方法中实现。
3.2 didPop
didPop 方法会在路由从导航器中弹出时被调用。它的参数和 didPush 方法相同。
使用场景:当我们需要在路由被弹出时执行一些操作时,可以在didPop方法中实现。
3.3 didRemove
didRemove 方法会在路由被从导航器中移除时被调用。它有两个参数:route 和 previousRoute ,分别表示被移除的路由和之前的路由。
使用场景:当我们需要在路由被移除时执行一些操作时,可以在didRemove方法中实现。
3.4 didReplace
didReplace 方法会在一个路由被另一个路由替换时被调用。它有两个参数:newRoute 和 oldRoute,分别表示新的路由和被替换的路由。
使用场景:当我们需要在路由被替换时执行一些操作时,可以在didReplace方法中实现。
下面是一个使用这些方法的例子:
在这个例子中,我们在每个方法中都打印了相关的信息,这样我们就可以清楚地看到路由的变化。
class MyRouteObserver extends NavigatorObserver {void didPush(Route route, Route previousRoute) {super.didPush(route, previousRoute);print('didPush ${route.settings.name}');}void didPop(Route route, Route previousRoute) {super.didPop(route, previousRoute);print('didPop ${route.settings.name}');}void didRemove(Route route, Route previousRoute) {super.didRemove(route, previousRoute);print('didRemove ${route.settings.name}');}void didReplace({Route newRoute, Route oldRoute}) {super.didReplace(newRoute: newRoute, oldRoute: oldRoute);print('didReplace ${oldRoute.settings.name} with ${newRoute.settings.name}');}
}
4. 路由观察者的应用
路由观察者在 Flutter 应用中有很多实际的应用场景,例如用于用户行为跟踪,页面切换动画等。
4.1 用户行为跟踪
在很多应用中,我们需要跟踪用户的行为,例如用户打开了哪些页面,停留在每个页面的时间等。这时,我们可以使用路由观察者来实现。
当用户打开一个新的页面时,didPush 方法会被调用,我们可以在这个方法中记录用户打开这个页面的时间;当用户关闭一个页面时,didPop 方法会被调用,我们可以在这个方法中记录用户关闭这个页面的时间。通过这种方式,我们就可以跟踪用户在每个页面的停留时间。
4.2 页面切换动画
在一些应用中,我们希望在页面切换时有一些特殊的动画效果。这时,我们也可以使用路由观察者来实现。
我们可以在 didPush 和 didPop 方法中添加动画效果。例如,当用户打开一个新的页面时,我们可以在 didPush 方法中添加一个淡入效果;当用户关闭一个页面时,我们可以在 didPop 方法中添加一个淡出效果。
下面是一个使用路由观察者来实现用户行为跟踪的例子:
class MyRouteObserver extends NavigatorObserver {void didPush(Route route, Route previousRoute) {super.didPush(route, previousRoute);print('User opened ${route.settings.name}');// 这里我们可以启动一个计时器来跟踪用户在这个页面上停留的时间。}void didPop(Route route, Route previousRoute) {super.didPop(route, previousRoute);print('User closed ${route.settings.name}');// 在这里,我们可以停止计时器,并获得用户在此页面停留的时间。}
}
在这个例子中,我们在 didPush 和 didPop 方法中分别打印了用户打开和关闭页面的信息,并且提到了如何使用计时器来跟踪用户在每个页面的停留时间。
5. 路由观察者的限制和注意事项
虽然路由观察者是一个非常强大的工具,但在使用过程中也有一些限制和需要注意的事项。
5.1 限制
仅仅监听 Navigator 进行的路由变化
- 路由观察者只能监听到通过 Navigator 进行的路由变化,如果路由变化是通过其他方式(例如直接修改组件的状态)进行的,那么路由观察者是无法监听到的。
PopScope
- 路由观察者的方法是在路由变化后被调用的,因此它不能阻止路由的变化。如果你需要在路由变化前进行一些操作(例如询问用户是否确定要离开当前页面),那么你需要使用其他的方法,例如 PopScope( WillPopScope 已经被废弃,使用PopScope替代)。
关于 PopScope 这里补充一个案例分析:
import 'package:flutter/material.dart';void main() => runApp(const NavigatorPopHandlerApp());class NavigatorPopHandlerApp extends StatelessWidget {const NavigatorPopHandlerApp({super.key});Widget build(BuildContext context) {return MaterialApp(// 设置初始路由为 '/home'initialRoute: '/home',// 定义路由表routes: <String, WidgetBuilder>{'/home': (BuildContext context) => const _HomePage(),'/two': (BuildContext context) => const _PageTwo(),},);}
}
class _HomePage extends StatefulWidget {const _HomePage();State<_HomePage> createState() => _HomePageState();
}// 首页的状态组件
class _HomePageState extends State<_HomePage> {Widget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const Text('Page One'), // 显示 "Page One" 文字TextButton(onPressed: () {Navigator.of(context).pushNamed('/two'); // 点击按钮后跳转到第二个页面},child: const Text('Next page'), // 显示 "Next page" 文字),],),),);}
}
// 第二个页面的组件
class _PageTwo extends StatefulWidget {const _PageTwo();State<_PageTwo> createState() => _PageTwoState();
}// 第二个页面的状态组件
class _PageTwoState extends State<_PageTwo> {// 显示一个对话框,询问用户是否确定离开void _showBackDialog() {showDialog<void>(context: context,builder: (BuildContext context) {return AlertDialog(title: const Text('Are you sure?'), // 对话框标题content: const Text('Are you sure you want to leave this page?', // 对话框内容),actions: <Widget>[TextButton(style: TextButton.styleFrom(textStyle: Theme.of(context).textTheme.labelLarge,),child: const Text('Nevermind'), // "Nevermind" 按钮onPressed: () {Navigator.pop(context); // 点击后关闭对话框},),TextButton(style: TextButton.styleFrom(textStyle: Theme.of(context).textTheme.labelLarge,),child: const Text('Leave'), // "Leave" 按钮onPressed: () {Navigator.pop(context); // 点击后关闭对话框Navigator.pop(context); // 并返回上一个页面},),],);},);}Widget build(BuildContext context) {return Scaffold(body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const Text('Page Two'), // 显示 "Page Two" 文字PopScope(canPop: false,onPopInvoked: (bool didPop) {if (didPop) {return;}_showBackDialog(); // 当用户尝试离开时,显示对话框},child: TextButton(onPressed: () {_showBackDialog(); // 点击按钮后显示对话框},child: const Text('Go back'), // 显示 "Go back" 文字),),],),),);}
}
这段代码是Flutter官方给出的一个案例,它包含两个页面,用户可以在这两个页面之间导航。当用户尝试离开第二个页面时,会弹出一个对话框询问用户是否确定离开。
5.2 注意事项
-
在使用路由观察者时,需要注意不要在路由观察者的方法中进行过于复杂的操作,因为这可能会影响到路由的性能。如果需要进行复杂的操作,建议在另一个异步任务中进行。
-
在使用路由观察者时,需要注意正确地管理路由观察者的生命周期。如果一个路由观察者被销毁了,但是你仍然试图在它的方法中访问一些资源,那么可能会导致错误。
-
在使用路由观察者时,需要注意处理好异常。因为路由观察者的方法是在路由变化后被调用的,如果在这些方法中发生了异常,那么可能会导致应用崩溃。
相关文章:
Flutter笔记:路由观察者
Flutter系列 路由观察者 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/details/134572181 目 录 1. 概述2. 路由…...
【驱动】串口驱动分析(三)-serial driver
简介 前两节我们介绍串口驱动的框架和tty core部分。这节我们介绍和硬件紧密相关的串口驱动部分。 UART驱动部分依赖于硬件平台,而TTY驱动和具体的平台无关。虽然UART部分依赖于平台,但是不管是哪个硬件平台,驱动的思路都是一致的ÿ…...
(C++20) constinit常量初始化
文章目录 由来constinit 常量初始化常量初始化 ! 初始化常量初始化声明静态存储对象非初始化声明thread_local END 由来 在C多文件编译中会出现一个常见的问题,叫做静态初始化顺序问题。Static Initialization Order Fiasco。 比如现在有两个文件,其中…...
python实现获取aws route53域名信息
最近由于工作原因接触到aws的服务,我需要实时获取所有的域名信息,用于对其进行扫描,因此写了一个自动化爬取脚本 给需要的人分享。 1.基础准备 代码环境:python3 第三方库:boto3 (安装方法pip install…...
Linux_Linux终端常用快捷键
Linux命令行核心常用快捷键是一些在终端中使用的快捷键组合,用于提高命令行操作的效率。下面是这些快捷键的原理详细解释、使用场景解释 Ctrl A :将光标移动到命令行的开头。这个快捷键的原理是发送一个控制序列到终端,告诉终端将光标移动到…...
Neo4j 数据库管理 数据备份与恢复(头歌)
文章目录 第1关:数据备份与恢复任务描述相关知识数据备份数据导入 编程要求测试说明答案测试前准备Cypher 代码数据备份与导入 第1关:数据备份与恢复 任务描述 本关任务:熟练掌握数据备份与恢复。 相关知识 为了完成本关任务,…...
TCP传输的三次握手四次挥手策略
TCP传输的三次握手四次挥手策略如下: 第一次握手:客户端发送一个带有SYN标志的数据包给服务器,并记为SYN_Client。第二次握手:服务器收到SYN_Client后,向客户端发送一个带有SYN和ACK标志的数据包,记为SYN_…...
在gitlab上使用server_hooks
文章目录 1. 前置条件2. Git Hook2.1 Git Hook 分为两部分:本地和远程2.1.1 本地 Git Hook,由提交和合并等操作触发:2.1.2 远程 Git Hook,运行在网络操作上,例如接收推送的提交: 3. 操作步骤3.1 对所有的仓…...
【云原生系列】Kubernetes知识点
目录 概念 基础架构 单master节点 多master节点 组件 Master节点核心组件 其他组件 请求发送流程 插件 核心资源 调度资源 Pod 创建pod组件间调用流程 pod生命周期: 初始化容器 镜像拉取策略 重启策略 钩子函数 探针 探针的实现方式 DownwardAP…...
Hugging-Face报错锦囊(不断更新)
requests.exceptions.SSLError: (MaxRetryError(“HTTPSConnectionPool(host‘huggingface.co’, port443): Max retries exceeded with url: /api/models/bert-base-chinese (Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certificate…...
Redis核心数据结构
目录 五种基础数据结构 string hash list set zset 用zset实现微博热搜 scan遍历 高频问题 五种基础数据结构 string 单个赋值set 批量赋值/取值 msetmget 设置不存在字符串setnx, 如果不存在, 则设置成功返回1, 如果存在返回0, 可以当做分布式锁 删除值 设置过期时…...
Redis 如何批量删除指定前缀的Key
批量删除指定前缀的Key有两中方法,一种是借助 redis-cli,另一种是通过 SCAN 命令来遍历所有匹配前缀的 key,并使用 DEL 命令逐个删除它们。 redis-cli 使用 Redis 自带的 redis-cli 命令行工具,你可以通过以下方式批量删除指定前…...
如何熟练使用vim工具?
🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏1: 🍔🍟🌯C语言初阶 🐻推荐专栏2: 🍔🍟🌯C语言进阶 🔑个人信条: 🌵知行合一 …...
ClassNotFoundException: org.apache.hive.spark.client.Job
hive使用的是3.13版本,spark是3.3.3支持hadoop3.x hive将engine从mr改成spark,通过beeline执行insert、delete时一直报错,sparkTask rpc关闭, 查看yarn是出现ClassNotFoundException: org.apache.hive.spark.client.Job。 开始…...
《合成孔径雷达成像算法与实现》_使用CS算法对RADARSAT-1数据进行成像
CSA 简介:Chirp Scaling 算法 (简称 CS 算法,即 CSA) 避免了 RCMC 中的插值操作。该算法基于 Scaling 原理,通过对 chirp 信号进行频率调制,实现了对信号的尺度变换或平移。基于这种原理,可以通过相位相乘代替时域插值…...
GCN01——Ubuntu中设置vivado编辑器为vscode
确定vscode位置 在命令行中输入 which code得到文件地址 进入文件夹后可看到,这是个链接文件,不过无所谓,就用这个地址就行 设置Text Editor 打开setting选择右侧text editor 这里说明了如何进行设置 将自己的地址加进去就行 /usr/share…...
Android 11.0 软硬键盘同时使用的兼容(软键盘与内置物理键盘共存)
1.概述 在11.0的系统rom产品定制化开发总,在有些设备上,如果外接了USB扫描枪之类的设备,当插入USB扫描枪以后,然后点击输入调用输入法的时候,没有反应,但是拔掉USB扫描枪以后,输入法又能正常使用,这说明和输入法起冲突了,询问了好多同时,说可能把会把USB扫描枪识别为…...
ARM安全架构——为复杂软件提供保护
目录 一、概述 二、栈溢出和执行权限 三、面向返回的编程ROP 四、面向跳转的编程(JOP) 五、将这些技术应用于实际代码 七、检查你的知识...
提升网页交互体验的秘密武器——防抖和节流
说在前面 在现代Web开发中,提高网页性能是至关重要的。本文介绍了防抖和节流这两种常用的性能优化技术,通过控制函数的执行频率,有效减少不必要的计算和网络请求,从而提升用户体验和页面加载速度。 函数节流 节流是指限制一个函数…...
HX3002入耳检测光感驱动调试-感0x08 寄存器溢出,不变化错误问题解决方法
是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 读取光感0x08 寄存器溢出,不变化错误问题?原因 原因:没有读取到0x08数据,没有读0x…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
