flutter 一個簡單的Route Helper/Navigator Helper

CaiJingLong發表於2018-09-24

在flutter中 route是一個繞不開,必須面對,且很常用東西

Route就是路由,顧名思義,負責你頁面間的跳轉

不想看程式碼和思路分析的直接copy了拿去用就行 沒有啥外部依賴,只需要注意_rootRoute 後面的字串需要和initialRoute 對應即可

路由又分靜態和動態路由

靜態就是不需要傳引數的,這樣的路由可以直接定義在MaterialApp/WidgetsApp 裡這樣可以通過Navigator.pushNamed呼叫

flutter 一個簡單的Route Helper/Navigator Helper

動態的就是傳入一個PageRoute, 通常是一個MaterialPageRoute 或者CupertinoPageRoute,或者你如果有自定義的有可以使用

這裡我使用一個我的工具類來實現跳轉,因為大部分情況下,工程中的路由都是動態的,也就是需要傳引數的,所以工具類中只包含了使用Widget相關的方案

import 'dart:async';
import 'package:flutter/material.dart';
class RouteHelper {
static Future<
T>
pushWidget<
T>
( BuildContext context, Widget widget, {
bool replaceRoot = false, bool replaceCurrent = false,
}) {
return pushRoute( context, MaterialPageRoute(builder: (ctx) =>
widget), replaceRoot: replaceRoot, replaceCurrent: replaceCurrent, );

} static Future<
T>
pushRoute<
T>
( BuildContext context, PageRoute<
T>
route, {
bool replaceRoot = false, bool replaceCurrent = false,
}) {
assert(!(replaceRoot == true &
&
replaceCurrent == true));
if (replaceRoot == true) {
return Navigator.pushAndRemoveUntil( context, route, _rootRoute, );

} if (replaceCurrent == true) {
return Navigator.pushReplacement(context, route);

} return Navigator.push(context, route);

}
}var _rootRoute = ModalRoute.withName("home");
複製程式碼

解析一下這個類,有兩個方法,一個是接受PageRoute,一個是接收Widget

接收Widget的是講Widget包裝為MaterialPageRoute,然後傳給另一個方法

另一個方法中包含3種情況,一種是替換根節點,一種是替換當前頁面(關閉當前,且開啟新頁面),還有一種就是平常的push(即 不關閉當前,直接開啟新的)

根據傳參不同而有所不同

有一個_rootRoute變數,這個變數的目的是用於替換根節點,'home'是我定義在MaterialApp裡的initialRoute,這樣一一對應才能確保替換根節點

image.png

當然這個類也可以繼續擴充套件,比如將routes定義在內,然後傳route name 引數,接著通過routes來提取出named對應的Widget/Route 接著傳入pushRoute方法進行跳轉即可


這個簡便的Helper還有另一個好處,就是可以方便後續批量替換Route實現,比如有一天你想自定義一個PageRoute,不使用MaterialRoute ,那麼你只需要替換如下如所示的部分即可

image.png

當然還可以有別的擴充套件方法來支援named比如檢視Navigator的原始碼發現pushNamed,就是通過widget.onGenerateRoute方法獲取到route的,我這裡直接在helper中寫就好了

image.png

Helper 寫完了,我們看看使用的方法使用起來也很簡單

比如強登陸應用

  void  _login() { 
RouteHelper.pushWidget(context, HomeRootPage(), replaceRoot: true);

}複製程式碼

這裡登入成功後,我直接替換了root節點,然後根路由就變成了主頁面

  void _forgetPwd() { 
RouteHelper.pushWidget(context, ForgetPwdPage());

} void _register() {
RouteHelper.pushWidget(context, RegiseterPage());

}複製程式碼

忘記密碼和註冊都基於登入在做,最終要返回登入,所以這裡用普通的呼叫方法

  _register() { 
RouteHelper.pushWidget( context, RegisterSuccessPage(), replaceCurrent: true, );

}複製程式碼

註冊成功後我這裡有一個單獨的註冊成功頁,寫了一些註冊後的注意事項,而返回又應該直接返回到登入頁面,所以這裡我需要替換掉當前的頁面,只用replaceCurrent 即可


當然方法接受返回值也是允許的

  _orderDetail(String item) async { 
//todo 檢視訂單詳情 var result = await RouteHelper.pushWidget<
bool>
(context, OrderDetailPage(id: item));
if (result == true) {
_refresh();

}
}複製程式碼

這裡如果在詳情頁買了東西/加到購物車,回到主頁面,是要重新整理頁面的,所以我們接收返回值,然後判斷

小tips:這裡之所以用result == true 而不是 if(result) 是因為dart中 bool是有3個值的 true false nullif(result==true) 可以將result 為 null的情況規避掉,提升程式碼健壯性,這個不得不說是dart 完全物件導向造成的副作用


來源:https://juejin.im/post/5ba8d95f5188255c6140cd38

相關文章