Flutter上線項目實戰(zhàn)記錄之路由篇
更新時間:2019年09月06日 14:20:12 作者:callme大帥
這篇文章主要給大家介紹了關(guān)于Flutter上線項目實戰(zhàn)記錄之路由篇的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Flutter具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
1. 應用場景
開發(fā)中經(jīng)常遇到
- 路由跳轉(zhuǎn)時拿不到context怎么辦,eg: token失效/異地登錄跳轉(zhuǎn)登錄頁面。
- 獲取不到當前路由名稱怎么辦,eg: 點擊push推送跳轉(zhuǎn)指定路由,如果已經(jīng)在當前頁面就replace,如果不在就push。
- 注冊監(jiān)聽路由跳轉(zhuǎn),做一些想做的事情 ,eg:不同路由,顯示不同狀態(tài)欄顏色。
- 等等...
2. 解決方案
解決思路:
- MaterialApp 的routes屬性賦值路由數(shù)組,navigatorObservers屬性賦值路由監(jiān)聽對象NavigatorManager。
- 在NavigatorManager里實現(xiàn)NavigatorObserver的didPush/didReplace/didPop/didRemove,并記錄到路由棧List _mRoutes中。
- 將實時記錄的路由跳轉(zhuǎn),用stream發(fā)一個廣播,哪里需要哪里注冊。
3. 具體實現(xiàn)
main.dart
MaterialApp( navigatorObservers: [NavigatorManager.getInstance()], routes: NavigatorManager.configRoutes, ... )
navigator_manager.dart
class NavigatorManager extends NavigatorObserver { /* 配置routes */ static Map<String, WidgetBuilder> configRoutes = { PackageInfoPage.sName: (context) => SplashPage.sName: (context) => SplashPage(), LoginPage.sName: (context) => SplashPage()), MainPage.sName: (context) => SplashPage(), //... } // 當前路由棧 static List<Route> _mRoutes; List<Route> get routes => _mRoutes; // 當前路由 Route get currentRoute => _mRoutes[_mRoutes.length - 1]; // stream相關(guān) static StreamController _streamController; StreamController get streamController=> _streamController; // 用來路由跳轉(zhuǎn) static NavigatorState navigator; /* 單例給出NavigatorManager */ static NavigatorManager navigatorManager; static NavigatorManager getInstance() { if (navigatorManager == null) { navigatorManager = new NavigatorManager(); _streamController = StreamController.broadcast(); } return navigatorManager; } // replace 頁面 pushReplacementNamed(String routeName, [WidgetBuilder builder]) { return navigator.pushReplacement( CupertinoPageRoute( builder: builder ?? configRoutes[routeName], settings: RouteSettings(name: routeName), ), ); } // push 頁面 pushNamed(String routeName, [WidgetBuilder builder]) { return navigator.push( CupertinoPageRoute( builder: builder ?? configRoutes[routeName], settings: RouteSettings(name: routeName), ), ); } // pop 頁面 pop<T extends Object>([T result]) { navigator.pop(result); } // push一個頁面, 移除該頁面下面所有頁面 pushNamedAndRemoveUntil(String newRouteName) { return navigator.pushNamedAndRemoveUntil(newRouteName, (Route<dynamic> route) => false); } // 當調(diào)用Navigator.push時回調(diào) @override void didPush(Route route, Route previousRoute) { super.didPush(route, previousRoute); if (_mRoutes == null) { _mRoutes = new List<Route>(); } // 這里過濾調(diào)push的是dialog的情況 if (route is CupertinoPageRoute || route is MaterialPageRoute) { _mRoutes.add(route); routeObserver(); } } // 當調(diào)用Navigator.replace時回調(diào) @override void didReplace({Route newRoute, Route oldRoute}) { super.didReplace(); if (newRoute is CupertinoPageRoute || newRoute is MaterialPageRoute) { _mRoutes.remove(oldRoute); _mRoutes.add(newRoute); routeObserver(); } } // 當調(diào)用Navigator.pop時回調(diào) @override void didPop(Route route, Route previousRoute) { super.didPop(route, previousRoute); if (route is CupertinoPageRoute || route is MaterialPageRoute) { _mRoutes.remove(route); routeObserver(); } } @override void didRemove(Route removedRoute, Route oldRoute) { super.didRemove(removedRoute, oldRoute); if (removedRoute is CupertinoPageRoute || removedRoute is MaterialPageRoute) { _mRoutes.remove(removedRoute); routeObserver(); } } void routeObserver() { LogUtil.i(sName, '&&路由棧&&'); LogUtil.i(sName, _mRoutes); LogUtil.i(sName, '&&當前路由&&'); LogUtil.i(sName, _mRoutes[_mRoutes.length - 1]); // 當前頁面的navigator,用來路由跳轉(zhuǎn) navigator = _mRoutes[_mRoutes.length - 1].navigator; streamController.sink.add(_mRoutes); } }
4. 如何使用
token失效跳轉(zhuǎn)
case 401: ToastUtil.showRed('登錄失效,請重新登陸'); UserDao.clearAll(); NavigatorManager.getInstance().pushNamedAndRemoveUntil(LoginPage.sName); break;
點擊push推送跳轉(zhuǎn)
static jumpPage(String pageName, [WidgetBuilder builder]) { String currentRouteName = NavigatorManager.getInstance().currentRoute.settings.name; // 如果是未登錄,不跳轉(zhuǎn) if (NavigatorManager.getInstance().routes[0].settings.name != MainPage.sName) { return; } // 如果已經(jīng)是當前頁面就replace if (currentRouteName == pageName) { NavigatorManager.getInstance().pushReplacementNamed(pageName, builder); } else { NavigatorManager.getInstance().pushNamed(pageName, builder); } }
監(jiān)聽路由改變狀態(tài)欄顏色
class StatusBarUtil { static List<String> lightRouteNameList = [ TaskhallPage.sName, //... ]; static List darkRoutNameList = [ SplashPage.sName, LoginPage.sName, MainPage.sName, //... ]; static init() { NavigatorManager.getInstance().streamController.stream.listen((state) { setupStatusBar(state[state.length - 1]); }) } setupStatusBar(Route currentRoute) { if (lightRouteNameList.contains(currentRoute.settings.name)) { setLight(); } else if (darkRoutNameList.contains(currentRoute.settings.name)) { setDart(); } } }
完結(jié),撒花🎉
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。
您可能感興趣的文章:
- Flutter路由框架Fluro使用簡介
- Flutter如何完成路由攔截,實現(xiàn)權(quán)限管理
- Flutter開發(fā)中的路由參數(shù)處理
- Flutter app頁面路由以及路由攔截的實現(xiàn)
- 詳解Flutter的路由導航
- flutter 路由跳轉(zhuǎn)的實現(xiàn)示例
- flutter 自定義websocket路由的實現(xiàn)
- Flutter開發(fā)之路由與導航的實現(xiàn)
- Flutter利用注解生成可自定義的路由的實現(xiàn)
- Flutter 局部路由實現(xiàn)詳解
- Flutter路由的跳轉(zhuǎn)、動畫和傳參詳解(最簡單)
- Flutter 路由插件fluro的使用
相關(guān)文章
android 仿微信demo——注冊功能實現(xiàn)(移動端)
本篇文章主要介紹了微信小程序-閱讀小程序?qū)嵗╠emo),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望能給你們提供幫助2021-06-06使用Android Studio檢測內(nèi)存泄露(LeakCanary)
本篇文章主要介紹了用Android Studio檢測內(nèi)存泄露的問題的解決方法,Android Studio在為我們提供了良好的編碼體驗的同時,也提供了許多對App性能分析的工具,下面我們一起來了解一下。2016-12-12實例講解Android app開發(fā)中ListView的基本使用及優(yōu)化
這篇文章主要介紹了Android app開發(fā)中ListView的基本使用及優(yōu)化,ListView視圖組件是Android中最常用的組件之一需要的朋友可以參考下2016-02-02