前言
这是博客 Flutter 路由原理解析的番外篇,如果你没有看过主篇真的不建议你直接看这篇文章,因为它真的炒鸡炒鸡枯燥乏味……
不讲客套话啦,我们分别从Navigator
的push
和pop
两个方法去探索源码以及一些重要的细节。
push
当我们想要push一个Page在界面上时,我们可以调用如下代码:
Navigator.push(
context,
PageRouteBuilder(pageBuilder: (context, animation, secondaryAnimation) {
return MyPage(args);
}));
复制代码
我们以Navigator.push(BuildContext context, Route<T> route)
方法为起始进行追述:
static Future<T> push<T extends Object>(BuildContext context, Route<T> route) {
return Navigator.of(context).push(route);
}
复制代码
1.NavigatorState
对象检索
就像上篇文章有提到过的,Navigator.push
是一个静态方法,使得你可以在任何地方进行调用,其内部通过of
方法在Element
树(BuildContext
是 Element
的抽象类)中进行向上搜索。我们看下Navigator.of
方法:
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;
}
复制代码
主要通过rootNavigator
变量判断是否要检索根部Navigator,rootAncestorStateOfType
向上查找最根部匹配类型对象,ancestorStateOfType
向上查找最近的匹配类型对象。从这个方法我们也可以知道Navigator.of
方法查找的不是Navigator
而是NavigatorState
,这个也比较容易理解,Navigator
是一个StatefulWidget
,具体的逻辑都在它的State对象当中。
2.push实现
接下来看NavigatorState.push
实现:
//0
final List<Route<dynamic>> _history = <Route<dynamic>>[];
Future<T> push<T extends Object>(Route<T> route) {
...
//1
final Route<dynamic> oldRoute = _history.isNotEmpty ? _history.last : null;
//2
route._navigator = this;
//3
route.install(_currentOverlayEntry);
//4
_history.add(route);
//5
route.didPush();
route.didChangeNext(null);
if (oldRoute != null) {
oldRoute.didChangeNext(route);
route.didChangePrevious(oldRoute);
}
//6
for (NavigatorObserver observer in widget.observers)
observer.didPush(route, oldRoute);
_afterNavigation();
return route.popped;
}
复制代码
-
0.
_history
就是Navigator
所维护的界面栈,但它只是一个普通的List
。 -
- 获取原本在栈顶的route,因为
_history
是一个普通的
- 获取原本在栈顶的route,因为