Navigator ,在 Flutter 中 Navigator 是管理一組組件跳轉的核心組件。使用棧的方式對組件進行管理。不只是在咱們平常使用開發組件跳轉中並且在程序入口 App 中,一樣是使用 Navigator 對組件的初始化進行管理。bash
Navigator 棧中管理的不單單的是UI類型組件,並且能管理 Navigator 類型的。以下圖所示:動畫
Navigator 的構造方法以及其參數源碼以下:ui
///navigator.dart 749行 源碼以下
/// Creates a widget that maintains a stack-based history of child widgets.
///
/// The [onGenerateRoute] argument must not be null.
const Navigator({
Key key,
this.initialRoute,
@required this.onGenerateRoute,
this.onUnknownRoute,
this.observers = const <NavigatorObserver>[],
}) : assert(onGenerateRoute != null),
super(key: key);
複製代碼
其中有三個比較重要的構造參數,第一個是 initialRoute ,類型是 String ,是本 Navigetor 初始化跳轉的 Route 對應的 name。onGenerateRoute 是一個帶有傳入參數 RouteSettings 方法,每當使用當前 Navigator 根據 name 進行頁面處理(push、pop等等)都會先走到這個方法進行查找,找出對應的route,RouteSettings 中帶有 name、傳遞參數 arguments ,在方法中須要根據 initialRoute 返回對應的 Route 而且初始化一些須要用 name 進行跳轉的 Route。onUnknownRoute 是當使用 pushNamed() 進行跳轉新頁面沒法在 onGenerateRoute 返回對應的 Route 時,則跳轉 onUnknownRoute。this
使用例子:spa
Navigator(
initialRoute: 'signup/personal_info',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch (settings.name) {
case 'signup/personal_info':
builder = (BuildContext _) => CollectPersonalInfoPage();
break;
case 'signup/choose_credentials':
builder = (BuildContext _) => ChooseCredentialsPage();
break;
default:
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(builder: builder, settings: settings);
},
);
複製代碼
Navigator 是一個 StatefulWidget ,因此具體的功能都是在 NavigatorState 中實現的。code
例如,咱們跳轉到一個新組件有兩種寫法。cdn
一種是server
Navigator.of(context).pushNamed('signup/choose_credentials');
///Navigator.of(context)
///navigator.dart 1449行 源碼以下:
static NavigatorState of(
BuildContext context, {
bool rootNavigator = false,
bool nullOk = false,
}) {
final NavigatorState navigator = rootNavigator
? context.rootAncestorStateOfType(const TypeMatcher<NavigatorState>())
: context.ancestorStateOfType(const TypeMatcher<NavigatorState>());
...省略非關鍵代碼
return navigator;
}
複製代碼
能夠看出來 .of(contaxt)
方法返回的是 NavigatorState ,也就是說實際調用 .pushNamed()
的是 NavigatorState。在 .of()
方法中有個比較重要的參數是 rootNavigator
,但咱們設置它爲 true 時,可以拿到入口 App 中的NavigatorState 進行操做。固然這裏的 App 中的 NavigatorState 並不能對全部的頁面都進行處理,如前面圖所示,假設 Navigator0 爲 App 的 NavigatorState ,它只能對 page一、page二、page三、page四、Navigator1 進行管理,同時, NavigatorState 並無提供一個獲取子 NavigatorState 的方法。blog
另外一種是開發
Navigator.pushNamed(context, routeName);
///navigator.dart 881行 源碼以下:
@optionalTypeArgs
static Future<T> pushNamed<T extends Object>(
BuildContext context,
String routeName, {
Object arguments,
}) {
return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
}
複製代碼
能夠看出這種跳轉的實際上是將第一種寫法封裝了下。
列舉一下經常使用的一些方法。
邏輯:
A->B->C->D
在D中調用如下方法, Navigetor 根據歷史頁面重新到舊 D->C->B->A 依次調用第二個參數傳入的方法而且在方法中傳入對應的Route,若傳入方法返回 true 結束調用,打開新頁面。
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(builder: (con) => PageMain()), (route) {
return false;
});
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(builder: (con) => PageMain()),
ModalRoute.withName("/"));
複製代碼
//替換,不顯示關閉當前頁面的過程。
Navigator.of(context).pushReplacement(pageMainRoute);
//有關閉當前頁面的動畫過程。源碼中的實現方式是先pop在push。
Navigator.of(context).popAndPushNamed(routeName);
複製代碼
//倒序關閉直到route名爲「/」
Navigator.of(context).popUntil(ModalRoute.withName("/"));
//倒序關閉直到返回true
Navigator.of(context).popUntil((route) {
return false;
});
複製代碼
//在新頁面關閉時會觸發 then ,返回值在方法的參數中。
Navigator.of(context)
.pushNamed('signup/choose_credentials')
.then((value) {
print(value);
});
//hello爲返回值
Navigator.of(context).pop("hello");
複製代碼
//二者結果同樣,均可以用來替換棧中的歷史頁面
Navigator.of(context).replace(
oldRoute: Routes.pageLoginRoute,
newRoute: CupertinoPageRoute(
builder: (conx) => PageMain()));
Navigator.replaceRouteBelow(
context, anchorRoute: Routes.pageLoginRoute,
newRoute: Routes.pageLoginRoute);
複製代碼
//移除某個頁面
Navigator.of(context).removeRoute(Routes.pageLoginRoute);
//移除某個頁面以及以後的頁面
Navigator.of(context).removeRouteBelow(Routes.pageLoginRoute);
複製代碼