Lao Meng's introduction: Many times we need to monitor the changes of the routing stack, so that we can customize the routing stack and facilitate the analysis of exception logs.
Use RouteObserver to listen for changes in the routing stack, first add navigatorObservers to the MaterialApp component:
void main() { runApp(MyApp()); } RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>(); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( ... navigatorObservers: [routeObserver], home: HomePage(), ); } }
The monitoring page settings are as follows:
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'); } }
Where didPush, didPushNext, didPopNext, didPop are callbacks for routing stack changes.
Jump from page A to page ARouteObserverDemo, the log output is as follows:
flutter: A-didPush route: /ARouteObserver
Entering this page only calls didPush.
Jump from the ARouteObserverDemo page to the BRouteObserverDemo page (same as the ARouteObserverDemo page, with monitoring set up), the log output is as follows:
flutter: A-didPushNext route: /ARouteObserver flutter: B-didPush route: /BRouteObserver
The didPushNext of the ARouteObserverDemo page is called first, and then the didPush of the BRouteObserverDemo page is called.
Execute pop from the BRouteObserverDemo page to return to the ARouteObserverDemo page, and the log output is as follows:
flutter: A-didPopNext route: /ARouteObserver flutter: B-didPop route: /BRouteObserver
The didPopNext of the ARouteObserverDemo page is called first, and then the didPop of the BRouteObserverDemo page is called.
The above case is only a routing stack change at the page level. If you want to know how the routing stack change of the entire application is handled?
One way is to write a base class that listens to the routing stack and that all pages inherit from this base class. This method is very intrusive to the source code.
Another way is to customize RouteObserver, inherit RouteObserver and override the methods in it:
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'); } }
use:
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(), ); } }
At this point, jump from page A to page B, and the log output is as follows:
flutter: didPush route: MaterialPageRoute<dynamic>(RouteSettings("/B", from 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)))
comminicate
comminicate
Lao Meng Flutter blog (330 control usage + practical entry series articles): http://laomengit.com
Welcome to join the Flutter exchange group (WeChat: laomengit), pay attention to the public account [Lao Meng Flutter]:
![]() |
![]() |