flutter: 2.0.1kraken: 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
是什么机会读取并传给引擎执行的:
- js生成节点如何与dart控件对应
- js引擎初始化的机会
- 运行指定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.createRenderObject3 _KrakenRenderObjectWidget.createElement4 _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引擎又是何时实现初始化的?