乐趣区

关于flutter:kraken-js执行时机

flutter: 2.0.1
kraken: main@b5574e6

查看源码肯定要带着问题,有针对性的理解不然会陷入代码的汪洋大海中,对于整个仓库有个通观概览的意识,先看成果。运行仓库中的示例代码 (kraken/example/assets/bundle.js) 能够看到生成了 flutter 节点控件:

源码片断如下:

var text1 = document.createTextNode('Hello World!');
var br = document.createElement('br');
var text2 = document.createTextNode('你好,世界!');
p.style.textAlign = 'center';
...
p.appendChild(text1);

于是很天然的,咱们想晓得 js 生成节点如何与 dart 控件对应的;要运行 js 文本那 js 引擎必须筹备好,它是如何初始化的;同时内部传入的 assets/bundle.js 是什么机会读取并传给引擎执行的:

  1. js 生成节点如何与 dart 控件对应
  2. js 引擎初始化的机会
  3. 运行指定 js 文件的机会

概览

从示例利用 (kraken/example/lib/main.dart) 的来看,入口还是绝对清晰的, 间接将 Kraken 对象作为 Scaffold 的 body 主体,接管了参数 assets/bundle.js 作为 bundlePath 的值,跟踪它就解决问题 3。

Kraken是一个无状态的 Widget, 创立的子控件为 _KrakenRenderObjectWidget, 它又是一个SingleChildRenderObjectWidget,这种控件是为了专门绘制单个节点的控件,最重要的 2 个办法:RenderObject createRenderObject(BuildContext context) 创立一个绘制对象;_KrakenRenderObjectElement createElement()创立控件对应的节点(Element)。

先明析一个概念,前端常常说到 渲染 ,但这里的渲染不是指具体的绘制操作,个别是输入一段 html 文本或者几个 vnode 节点交由浏览器作解析,离绘制还有很长一段距离。flutter 里的RenderObject(渲染对象) 是真正的绘制,在这里须要有尺寸,内容,色值,画刷等相干的对象去进行绘制操作(离屏幕上呈现绘制内容其实也有不小的间隔),所以为了避免一些名词上的凌乱,一律以绘制代替渲染。

另一个概念是节点 Element,flutter 里的 Element 不辨别 TextNode 也没有显式的 appendChild 操作,也不是 html/xml 文本里说的元素,它由 Widget 创立 (Element createElement() 是 Widget 的形象办法)并且与 Widget 一一对应。

再一个须要回顾的是 flutter 框架如何建设控件节点树相干的一些机制。简而言之,咱们是先得有 Widget 对象,它来创立一个节点(Element), 节点具体做父子关系建设的工作,这样节点树通过各种类型的 Widget 及其 build 办法建设起来,这一步由 flutter 框架实现的,内部不能自己持有节点自行建设层级关系,这一过程叫做挂载(mount)。

所以就能够明确 _KrakenRenderObjectElement 的惟一办法 void mount(Element parent, dynamic newSlot) async { 的作用了。

Widget Kraken.build(BuildContext)void _KrakenRenderObjectElement.mount(Element parent, dynamic newSlot)是异步的,两头显然创立了十分多的货色,一步一步来看。

于是按下面的概览总体的分了 4 步:

1 Kraken.build()
  _KrakenRenderObjectWidget()

2 _KrakenRenderObjectWidget.createRenderObject

3 _KrakenRenderObjectWidget.createElement

4 _KrakenRenderObjectElement.mount

步骤 1 简直没什么操作,只是生成对象持有内部传入数据

步骤 4 的代码也不多,其实曾经晓得问题 3 的答案了,不确定的话查找一下传入的 _bundlePath 的最终援用,其实就是在 KrakenController.loadBundle 这个办法里。深刻代码再看一下办法调用:

4 _KrakenRenderObjectElement.mount
  4.1 KrakenController.loadBundle
    KrakenBundle.getBundle
      AssetsBundle()
      *AssetsBundle.resolve
  4.2 _evalBundle
    controller.evalBundle()
      KrakenBundle.eval
        evaluateScripts
          _evaluateScripts
            'evaluateScripts'

就 2 步 4.1 载入资源 js 文本,具体解析资源的是AssetsBundle, 基类是KrakenBundle

4.2 调用 js 引擎求值 (evaluate),这里用了个全局办法_evalBundle,真是匪夷所思的操作,所有对象都在KrakenController 里还搞个全局办法;最终通过 dart 的 ffi 调用了 js 引擎库的办法 'evaluateScripts'

于是问题 3 答案近在眉睫:
Kraken 是在挂载节点的时候读取内容,再由 js 引擎执行

问题接踵而至 js 引擎又是何时实现初始化的?

退出移动版