老孟导读:很多时候咱们须要监听路由堆栈的变动,这样能够自定义路由堆栈、不便剖析异样日志等。

监听路由堆栈的变动应用 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: /ARouteObserverflutter: B-didPush route: /BRouteObserver

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

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

flutter: A-didPopNext route: /ARouteObserverflutter: 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】: