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);
复制代码