在Flutter開發中,全局的Toast
/Loading
很狗血,實現已有的實現方法都不是很人性化。最近在Dio作請求攔截器的時候Overlay
一直獲取不到context
,每一個頁面進入都存一遍很不方便,若是在MaterialApp
中存context,那麼調用Navigator.of(context).pushReplacementNamed
等removeUtils
的操做時都會報錯。android
除了以上坑點。在使用命名路由的時候動畫Flutter也沒提供修改方法。Navigator.pushNamed(context, "/login");
若是是android
那麼動畫就是從下而上,一點都不fashion。git
Flutter的路由很特殊,若是想實現一個Router鉤子要怎麼辦呢? - -!
我就是樣攔截路由,不管是埋點或者是之前其餘特殊功能。都須要一個統一的路由調度。程序員
爲了解決上面的Flutter坑點,聯繫Web端很是流行的SPA
應用,若是咱們的頁面一直是單頁那麼context
就是全局的。並且能夠實現頁面的攔截器。很是nice
。github
直接上代碼,首先實現一個單頁的頁面管理器。 so easy...app
MaterialApp( home: ManagerPage(), // ... )
而後是頁面管理器ManagerPage
的實現,利用Flutter自帶的Navigator
,不熟悉的童鞋能夠看看我之前寫的關於Navigator
的文章。動畫
Widget build(BuildContext context) { // 利用 EventBus 來調度 eventBus.on('showToast', (message) { Toast.show(context, message); }); return Navigator( // 實現SPA initialRoute: '/', onGenerateRoute: (RouteSettings settings) { // 路由表對應單頁 Widget _page = ZRouter.routerStore[settings.name]; // 埋點等操做 // 自定義路由動畫 return CupertinoPageRoute( settings: settings, builder: (context) => _page ); } ); }
關於routerStore
,一個SPA路由表ui
static Map<String, Widget> get routerStore => { '/': SplashPage(), '/main_page': NavPage(), '/login': LoginPage(), '/product_detail': ProductDetailsPage() };
在子頁面使用code
// 直接經過 Navigator.pushNamed 命名路由和傳參。 Navigator.pushNamed(context, "/login", arguments: RouteArguments<String>('想從活動登錄')); // 使用全局toast eventBus.emit('showToast', '系統繁忙請稍後再試...');
對請求攔截器的適配router
onResponse: (Response response) { // 在返回響應數據以前作一些預處理 if (response.data['code'] != '000') { eventBus.emit('showToast', '系統繁忙請稍後再試...'); } return response; }, onError: (DioError error) { // 當請求失敗時作一些預處理 eventBus.emit('showToast', '程序員GG正在想問題...'); return error; }