在路由剖析前篇已经讲了Navigator的初始化,路由的映射生成以及观察订阅,这个篇章则会侧重于路由的形态以及路由的本质。git
咱们仍是回到NavigatorState
的push
方法,github
方法虽然不长,信息量却很多,简要来讲,有这么几点:ide
作的事情无外乎就是从_history
取出oldRoute
, 把route
加入_history
,而后各自调用oldRoute
,route
的一些相似生命周期的方法, 最后返回route.poped
。其中有个很特别的地方是调用了route.install()
,这个咱们待会再讲。post
_history
很好理解,它是个List
,做为栈存储每个路由,push, pop操做分别对应List
的add
,removeLast
。学习
接着咱们看到Route
这个类,铺垫了这么久,终于要见到路由本尊了,老规矩,先一览全部👀。ui
Route
的内置方法咱们能够简单分红三类:
didPop
,didPush
等等isCurrent
,isFirst
,isActive
等前两类咱们就不讲了,由于知其名而知其意😎。而install
就神秘的很,毕竟它就是路由的核心了,不知道读者们有没有发现,其实讲到如今,Navigator
和Route
的关联仍是很模糊,而install
将会揭开这二者之间的鲜为人知的秘密(别问我为何知道的这么清楚,由于我事先看过🤣)。spa
对于install
方法,其中有个很重要的类,那就是OverlayEntity
, 它提供了Overlay
所须要的信息,如opaque
等,而Overlay
如其名,是一个悬浮覆盖的widget,因此说一个好的名字是多么重要,相信大家也恍然大悟了吧。路由的本质就是就是把咱们的页面包含在Overlay
这个widget里面,而后覆盖在旧的页面上去。因此对于弹框来讲,也就很好理解了,就是把弹框放入一个透明的Overlay
里面,而后盖在当前的页面上面,牛逼🐮!
知道这个关联以后,咱们下一步就是找出Route
到OverlayEntity
的转换关系,咱们先从平时使用的MaterialPageRoute
入手,深扒它的父类,最后在ModalRoute
找到了这么一个方法,3d
@override
Iterable<OverlayEntry> createOverlayEntries() sync* {
yield _modalBarrier = OverlayEntry(builder: _buildModalBarrier);
yield OverlayEntry(builder: _buildModalScope, maintainState: maintainState);
}
复制代码
接着咱们顺藤摸瓜,找到ModalRoute
对应的build
方法,看到了这么一个关键:code
widget.route.buildPage
这不是摆明告诉咱们是在这里建立的页面吗,而后咱们返回MaterialPageRoute
,果不其然cdn
因此,综上,咱们的路由页面经过buildPage
做为widget传递到ModalRoute
,接着在ModalRoute
经过createOverlayEntries
将路由页面包装在Overlay
这个覆盖型的widget。因此install
就是这么一个过程,它将路由页面映射为Overlay
,而Navigator
则负责管理路由的进出。
讲完 install
,再回过头看看刚刚的疑问,还有一个地方没解决的,那就是push以后的返回值route.popped
, 究竟为何须要这么一个返回值呢?其实这就是涉及到路由之间的通讯了,当页面退出时,能够携带一些信息回到上一个页面。以下:
能够看到,pop
方法的参数result
传递到了didPop
,那咱们继续扒一扒didPop
,
这里又发现了一个新大陆_popCompleter
🙄, 它是个啥呢,官方介绍以下Completer
:
A way to produce Future objects and to complete them later with a value or error.
复制代码
它是个能够延后执行的Future对象,那这样一来就串起来了,路由pop
以后,执行了_popCompleter
的完成方法,参数天然就经过Future对象传递出去,上一个页面只须要监听_popCompleter
的回调便可,这时候就轮到push
以后的返回值route.popped
登场了,没错,这个返回值就是_popCompleter
的Future对象,以下:
Future<T> get popped => _popCompleter.future;
复制代码
因此,梳理一下,当咱们push
一个路由的时候,咱们会拿到下一个路由的 Future对象,当下一个路由pop
的时候,Future对象就执行回调,以下:
Navigator.of(context).push(MaterialPageRoute(builder:(context) => SettingsPage()).then((value){
print(value);
});
复制代码
这样一来,咱们就能够监听到路由传递回来的值了。
其实能够简单粗暴地根据opaque
将路由划分为两类:
对应的其实就是弹框和页面,对于页面级的路由,继承自PageRoute
, 对应的opaque
为true,不透明页面;而弹框继承自PopupRoute
, opaque
为false,透明页面,因此呈现为弹框的形态。
其实这个篇章主要是经过深究push
方法,从中窥探路由的本质,对于路由来说,追溯到底,它仍是widget
,只不过藏得比较深。其实再复杂的东西,一层一层剖开,它仍然是一个系统最基本最核心的个体,这个剖析的过程尚且容易,最难的每每是从0到1,简单到复杂,这须要极大的智慧去搭建,组装和落地。
点击flutter_demo,查看完整代码。