日志

全局监听路由堆栈变化

 来源    2020-09-17    1  

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

监听路由堆栈的变化使用 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】:

相关文章
angular 全局 监听路由变化
日志app.run(['$rootScope', '$location', function($rootScope, $location) { /* 监听路由的状态变化 */ $rootScope.$on ...
1
react如何监听路由url变化
日志"componentWillReceiveProps" "shouldComponentUpdate" "componentWillUpdate&qu ...
1
angular的路由和监听路由的变化和用户超时的监听
日志先看两篇博客:http://camnpr.com/javascript/1652.html 这一篇博客是重点中的重点:                   http://www.tuicool.com ...
vue 监听路由变化
日志方法一:通过 watch // 监听,当路由发生变化的时候执行 watch:{ $route(to,from){ console.log(to.path); } }, 或 // 监听,当路由发生变化的 ...
3
转载 AngularJS监听路由变化
日志一.Angular 路由状态发生改变时可以通过' $stateChangeStart '.' $stateChangeSuccess '.' $stateChangeError '监听,通过注入'$l ...
1
Vue--watch控制监听路由地址-组件的变化----'$route.path': function (newVal, oldVal)
日志<!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8&q ...
1
vue监听路由变化
日志使用 watch,观察路由,一旦发生变化便重新获取数据 watch: { // 如果路由有变化,会再次执行该方法 '$route': 'fetchData' }
1
vue 如何通过监听路由变化给父级路由菜单添加active样式
日志1.项目需求:在项目开发中,多级菜单的情况下,勾选子菜单时,需要在父级菜单添加active样式. 2.遇到的问题:一级路由菜单的话,点击当前路由会自动在路由标签上添加router-link-exact ...
Angular 监听路由变化事件
日志摘要: $stateChangeStart- 当模板开始解析之前触发 $rootScope.$on('$stateChangeStart', function(event, toState, toPa ...
1
vue页面内监听路由变化
日志beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当钩子执行前,组件实 ...
1
Node.js监听MongoDB的变化
问答Node.js是否有办法监听MongoDB集合中特定数据的变化,并在发生变化时触发事件?::我相信你正在寻找database trigger. 不幸的是,MongoDB还没有支持它们,所以我认为你不能 ...
1
jQuery全局监听自定义事件
问答我正在尝试做的简化版本如下: var indication = $('#some-div'); indication.bind('custom-event', function() { ... } / ...
1
javascript – jQuery:如何监听DOM的变化?
问答是可能的,如何通过jQuery监听整个DOM树的变化? 我的具体问题:当您在任何html元素上进行悬停时,我有一个"工具提示"功能以时尚的方式显示标题属性的内容.然而,当您执行悬停 ...
1
转载 实时监听输入框值变化的完美方案:oninput & onpropertychange
日志oninput 是 HTML5 的标准事件,对于检测 textarea, input:text, input:password 和 input:search 这几个元素通过用户界面发生的内容变化非常有 ...
1
实时监听输入框值变化的完美方案:oninput & onpropertychange
日志原文:实时监听输入框值变化的完美方案:oninput & onpropertychange 在 Web 开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkey ...
1
vue 监听页面宽度变化 和 键盘事件
日志vue 监听页面窗口大小 export default { name: 'Full', components: { Header, Siderbar }, data () { return { scr ...
1
vue监听浏览器窗口大小变化
日志首先,页面初始化mounted的时候,通过 document.body.clientWidth 和 document.body.clientHeight 来获取到浏览器的宽和高,然后通过 window ...
1
angular2监听页面大小变化
日志一.现象 全屏页面中的图表,在很多的时候需要 resize 一把,以适应页面的大小变化 二.解决 1.引入 : import { Observable } from 'rxjs'; 2.使用(在ngO ...
js/jquery 实时监听输入框值变化的完美方案:oninput & onpropertychange
日志(1) 先说jquery, 使用 jQuery 库的话,只需要同时绑定 oninput 和 onpropertychange 两个事件就可以了,示例代码: $('#username').bind('i ...
JS 获取和监听屏幕方向变化(portrait / landscape)
日志移动设备的屏幕有两个方向: landscape(横屏)和portrait(竖屏),在某些情况下需要获取设备的屏幕方向和监听屏幕方向的变化,因此可以使用Javascript提供的 MediaQueryL ...
1