老孟導讀:不少時候咱們須要監聽路由堆棧的變化,這樣能夠自定義路由堆棧、方便分析異常日誌等。git
監聽路由堆棧的變化使用 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(), ); } }
監聽頁面設置以下:less
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 爲路由堆棧變化的回調。ide
從 A 頁面跳轉到 ARouteObserverDemo 頁面,日誌輸出以下:ui
flutter: A-didPush route: /ARouteObserver
進入此頁面只調用了 didPush。this
從 ARouteObserverDemo 頁面跳轉到 BRouteObserverDemo 頁面(同 ARouteObserverDemo 頁面,設置了監聽),日誌輸出以下:日誌
flutter: A-didPushNext route: /ARouteObserver flutter: B-didPush route: /BRouteObserver
先調用了 ARouteObserverDemo 頁面的 didPushNext,而後調用了 BRouteObserverDemo 頁面的 didPush。code
從 BRouteObserverDemo 頁面執行 pop 返回 ARouteObserverDemo 頁面,日誌輸出以下:server
flutter: A-didPopNext route: /ARouteObserver flutter: B-didPop route: /BRouteObserver
先調用了 ARouteObserverDemo 頁面的 didPopNext,而後調用了 BRouteObserverDemo 頁面的 didPop。blog
上面的案例僅僅是頁面級別的路由堆棧變化,若是想知道整個應用程序路由堆棧變化如何處理?
一種方法是寫一個監聽路由堆棧的基類,全部頁面繼承此基類。此方法對源代碼的侵入性很是高。
還有一種方法是自定義 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】:
![]() |
![]() |