全局Toast/Loading問題
在Flutter開發中,全局的Toast
/Loading
很狗血,實現已有的實現方法都不是很人性化。最近在Dio做請求攔截器的時候Overlay
一直獲取不到context
,每個頁面進入都存一遍很不方便,如果在MaterialApp
中存context,那麼調用Navigator.of(context).pushReplacementNamed
等removeUtils
的操作時都會報錯。
全局自定義命名路由動畫問題
除了以上坑點。在使用命名路由的時候動畫Flutter也沒提供修改方法。Navigator.pushNamed(context, "/login");
如果是android
那麼動畫就是從下而上,一點都不fashion。
頁面路由攔截器問題
Flutter的路由很特殊,如果想實現一個Router鉤子要怎麼辦呢? - -!
我就是樣攔截路由,無論是埋點或者是以前其他特殊功能。都需要一個統一的路由調度。
解決思路
爲了解決上面的Flutter坑點,聯繫Web端非常流行的SPA
應用,如果我們的頁面一直是單頁那麼context
就是全局的。而且可以實現頁面的攔截器。非常nice
。
SPA 單頁面應用解決方案
直接上代碼,首先實現一個單頁的頁面管理器。 so easy...
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路由表
static Map<String, Widget> get routerStore => {
'/': SplashPage(),
'/main_page': NavPage(),
'/login': LoginPage(),
'/product_detail': ProductDetailsPage()
};
在子頁面使用
// 直接通過 Navigator.pushNamed 命名路由和傳參。
Navigator.pushNamed(context, "/login", arguments: RouteArguments<String>('想從活動登陸'));
// 使用全局toast
eventBus.emit('showToast', '系統繁忙請稍後再試...');
對請求攔截器的適配
onResponse: (Response response) {
// 在返回響應數據之前做一些預處理
if (response.data['code'] != '000') {
eventBus.emit('showToast', '系統繁忙請稍後再試...');
}
return response;
},
onError: (DioError error) {
// 當請求失敗時做一些預處理
eventBus.emit('showToast', '程序員GG正在想問題...');
return error;
}