此异常最初是在此调用堆栈中引发的:_全局监听路由堆栈变化

news/2024/7/2 2:13:24

96a9c9e38c0f3ae3d64445f41c1a053d.png

老孟导读:很多时候我们需要监听路由堆栈的变化,这样可以自定义路由堆栈、方便分析异常日志等。

监听路由堆栈的变化使用 RouteObserver ,首先在 MaterialApp 组件中添加 navigatorObservers

void main() {
  runApp(MyApp());
}

RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
      navigatorObservers: [routeObserver],
      home: HomePage(),
    );
  }
}

监听页面设置如下:

class ARouteObserverDemo extends StatefulWidget {
  @override
  _RouteObserverDemoState createState() => _RouteObserverDemoState();
}

class _RouteObserverDemoState extends State<ARouteObserverDemo> with RouteAware {

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: Alignment.center,
        child: RaisedButton(
          child: Text('A RouteObserver'),
          onPressed: () {
            Navigator.of(context).pushNamed('/BRouteObserver');
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    routeObserver.unsubscribe(this);
  }

  @override
  void didPush() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPush route: $route');
  }

  @override
  void didPopNext() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPopNext route: $route');
  }

  @override
  void didPushNext() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPushNext route: $route');
  }

  @override
  void didPop() {
    final route = ModalRoute.of(context).settings.name;
    print('A-didPop route: $route');
  }

}

其中 didPush、didPushNext、didPopNext、didPop 为路由堆栈变化的回调。

从 A 页面跳转到 ARouteObserverDemo 页面,日志输出如下:

flutter: A-didPush route: /ARouteObserver

进入此页面只调用了 didPush。

从 ARouteObserverDemo 页面跳转到 BRouteObserverDemo 页面(同 ARouteObserverDemo 页面,设置了监听),日志输出如下:

flutter: A-didPushNext route: /ARouteObserver
flutter: B-didPush route: /BRouteObserver

先调用了 ARouteObserverDemo 页面的 didPushNext,然后调用了 BRouteObserverDemo 页面的 didPush。

从 BRouteObserverDemo 页面执行 pop 返回 ARouteObserverDemo 页面,日志输出如下:

flutter: A-didPopNext route: /ARouteObserver
flutter: B-didPop route: /BRouteObserver

先调用了 ARouteObserverDemo 页面的 didPopNext,然后调用了 BRouteObserverDemo 页面的 didPop。

上面的案例仅仅是页面级别的路由堆栈变化,如果想知道整个应用程序路由堆栈变化如何处理?

一种方法是写一个监听路由堆栈的基类,所有页面继承此基类。此方法对源代码的侵入性非常高。

还有一种方法是自定义 RouteObserver,继承RouteObserver并重写其中的方法:

class MyRouteObserver<R extends Route<dynamic>> extends RouteObserver<R> {
  @override
  void didPush(Route route, Route previousRoute) {
    super.didPush(route, previousRoute);
    print('didPush route: $route,previousRoute:$previousRoute');
  }

  @override
  void didPop(Route route, Route previousRoute) {
    super.didPop(route, previousRoute);
    print('didPop route: $route,previousRoute:$previousRoute');
  }

  @override
  void didReplace({Route newRoute, Route oldRoute}) {
    super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
    print('didReplace newRoute: $newRoute,oldRoute:$oldRoute');
  }

  @override
  void didRemove(Route route, Route previousRoute) {
    super.didRemove(route, previousRoute);
    print('didRemove route: $route,previousRoute:$previousRoute');
  }

  @override
  void didStartUserGesture(Route route, Route previousRoute) {
    super.didStartUserGesture(route, previousRoute);
    print('didStartUserGesture route: $route,previousRoute:$previousRoute');
  }

  @override
  void didStopUserGesture() {
    super.didStopUserGesture();
    print('didStopUserGesture');
  }
}

使用:

void main() {
  runApp(MyApp());
}

MyRouteObserver<PageRoute> myRouteObserver = MyRouteObserver<PageRoute>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      navigatorObservers: [myRouteObserver],
      initialRoute: '/A',
      home: APage(),
    );
  }
}

此时从 A 页面 跳转到 B 页面,日志输出如下:

flutter: didPush route: MaterialPageRoute<dynamic>(RouteSettings("/B", 来自A), animation: AnimationController#6d429(▶ 0.000; for MaterialPageRoute<dynamic>(/B))),previousRoute:MaterialPageRoute<dynamic>(RouteSettings("/A", null), animation: AnimationController#e60f7(⏭ 1.000; paused; for MaterialPageRoute<dynamic>(/A)))

交流

交流

老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】


http://www.niftyadmin.cn/n/712377.html

相关文章

web前端学习(八)——HTML5中表格、边框的相关标签设置

1.HTML中表格边框的相关标签 ①表格由 <table> 标签来定义。 ②每个表格均有若干行&#xff08;由 <tr> 标签定义&#xff09;&#xff0c;每行被分割为若干单元格&#xff08;由 <td> 标签定义&#xff09;。字母 td 指表格数据&#xff08;table data&…

C笔记

2019独角兽企业重金招聘Python工程师标准>>> Head first C cppcourse c part K&R C Bible##Head first C P6:如果想检查program的exit status, windows使用echo %ErrorLevel%, Linux使用echo $? (钱的问题) P9:顺序执行两条命令 gcc zork.c -o zork &&…

java私有_java关键字private(私有)

private关键字&#xff1a;是一个权限修饰符&#xff1b;用于修饰成员(成员变量和成啊元函数)&#xff1b;被私有化的成员只能在本类中有效&#xff1b;常用之一&#xff1a;将成员变量私有化&#xff0c;对外提供对应的set&#xff0c;get方法对其进行访问。提高对数据访问的安…

移动安全:BYOD时代的系统升级管理

所有智能手机用户都非常熟悉系统升级过程&#xff1a;每隔一段时间&#xff0c;你的设备都会收到升级推送&#xff0c;改变用户界面或者更改控制方法。 很多人不知道的是&#xff0c;用户界面外观的变化通常也包含那些会清理安全漏洞的补丁。 在消费电子世界中&#xff0c;这并…

SpringMVC interceptor拦截器

这是和登录有关的拦截器 创建拦截器的实现类 重写它的3个方法 Component public class TestInterceptor implements HandlerInterceptor {第一个方法: 请求在进入Handler之前, 该方法会被调用. 如果返回true, 则表示该请求会继续往下执行, 也就是才会执行到Handler 如果返回fal…

常见shell操作

一、find命令详细 find命令 -- 之查找指定时间内修改过的文件 比如我们要查找linux下指定时间内做过改动的文件&#xff0c;我们可以用find命令&#xff0c;其实find命令的功能十分强大&#xff0c;下面我们通过几个简单的例子来学习下find命令的简单用法&#xff1a; find /op…

python struct 用法_Python标准库笔记struct模块的使用

最近在学习python网络编程这一块&#xff0c;在写简单的socket通信代码时&#xff0c;遇到了struct这个模块的使用&#xff0c;当时不太清楚这到底有和作用&#xff0c;后来查阅了相关资料大概了解了&#xff0c;在这里做一下简单的总结。了解c语言的人&#xff0c;一定会知道s…

从人机大战看智能安防三大趋势

安防三大智能化趋势 在安防智能化进程中&#xff0c;实际上要解决三个问题&#xff1a;数据结构化、业务智能化、应用大数据化。总的来说就是三大智能化趋势&#xff1a;结构化的智能、业务的智能、大数据的智能。 由于安防本身业务应用的需求决定了安防人工智能市场的潜在需求…