Flutter学习篇(六)——路由剖析终篇

导航

前言

路由剖析前篇已经讲了Navigator的初始化,路由的映射生成以及观察订阅,这个篇章则会侧重于路由的形态以及路由的本质。git

剖析

咱们仍是回到NavigatorStatepush方法,github

方法虽然不长,信息量却很多,简要来讲,有这么几点:ide

  • Route
  • _history
  • return route.popped

作的事情无外乎就是从_history取出oldRoute, 把route加入_history,而后各自调用oldRoute,route的一些相似生命周期的方法, 最后返回route.poped。其中有个很特别的地方是调用了route.install(),这个咱们待会再讲。post

_history

_history很好理解,它是个List,做为栈存储每个路由,push, pop操做分别对应Listadd,removeLast学习

Route

接着咱们看到Route这个类,铺垫了这么久,终于要见到路由本尊了,老规矩,先一览全部👀。ui

Route的内置方法咱们能够简单分红三类:

  1. 生命周期类型,didPop,didPush等等
  2. 状态类型,isCurrent,isFirst,isActive
  3. install

前两类咱们就不讲了,由于知其名而知其意😎。而install就神秘的很,毕竟它就是路由的核心了,不知道读者们有没有发现,其实讲到如今,NavigatorRoute的关联仍是很模糊,而install将会揭开这二者之间的鲜为人知的秘密(别问我为何知道的这么清楚,由于我事先看过🤣)。spa

对于install方法,其中有个很重要的类,那就是OverlayEntity, 它提供了Overlay所须要的信息,如opaque等,而Overlay如其名,是一个悬浮覆盖的widget,因此说一个好的名字是多么重要,相信大家也恍然大悟了吧。路由的本质就是就是把咱们的页面包含在Overlay这个widget里面,而后覆盖在旧的页面上去。因此对于弹框来讲,也就很好理解了,就是把弹框放入一个透明的Overlay里面,而后盖在当前的页面上面,牛逼🐮!
知道这个关联以后,咱们下一步就是找出RouteOverlayEntity的转换关系,咱们先从平时使用的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

builder是咱们传进去的生成widget的方法,在这里生成了widget。

因此,综上,咱们的路由页面经过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,查看完整代码。

参考

相关文章
相关标签/搜索