Flutter框架原理探索

最近参与了Flutter项目模块的开发工作,同时很好奇Flutter内部的原理是什么,于是做了些研究;Flutter是一种“响应式框架”,与React类似;开发人员面向的是Widget,相当于View,没有Activity或者ViewController的概念;再深入探索,Widget其实只是负责配置数据,真正的处理渲染是Element、RenderObject;在理解框架原理之后再使用Flutter确实会生动很多。

一、框架

image.png

还是先从flutter的架构入手,它分为Framework层和Engine层两部分,其中Framework用的是Dart语言,Engine是C++,可以理解为Engine是Framework和Android/iOS的桥梁;先来简单看一下,分析上面的架构图,Framework层有两种样式规则Material(Android)、Cupertino(iOS),开发人员只需关心Widgets(配置信息),在内部进行渲染,其中包括动画、布局、绘制等,将渲染后的图层送入Engine,Engine包括Skia(渲染引擎)文字处理引擎等。

二、渲染流水线

image.png

接下来看下它的渲染流水线,GPU发送Vsync(垂直同步信号)通过Engine层,发送给Framework,Framework接收到信号进行动画、构建、布局、绘制顺序依次进行,最终渲染成Layer Tree 发给GPU;

那么GPU发送Vsync的时机是什么呢?其实在状态发生变化的时候(比如调用State.setState()),此时Framework层会发送Vsync请求给Engine,Engine接收到后告知系统,系统会发送Vsync信号再次通过Engine传递给Framework,Framework接收到信号后进行渲染。

三、布局渲染

image.png

接上面,Render tree来负责布局渲染,过程中需要绘制RenderObject所有子树,所以我们看到的界面是由很多layer组合成的,也就是layer tree。渲染机制是这样的,由GPU发送Vsync信号,通知Framework更新一帧,在UI线程中通过build、layout和paint渲染成Layer Tree,不过此时的渲染结果仍是矢量描述数据,怎么做才能转成让用户看得见的直观视图呢?这就要Engine通过“光栅化”将矢量描述数据生成一个个的像素填充数据;之后传入GPU线程组合Layer Tree,由Skia渲染引擎渲染后送给GPU展示。

四、State生命周期

image.png

State由Statefulwidget创建维护,这里说一下,Statefulewidget不是RenderObjectWidget,也就是它只有Elment没有RenderObject,所以它不能渲染对象,它的职责是维护State,接下来看下State的生命周期。

initState:初始化

build:经过初始化准备好State后,通过build构建,如statelessWidget的build,StatefulWidget State的bulid

deactivate:State从视图树暂时删除,如页面跳转切换

dispose:State从视图树永久移除

didiUpdateConfig:Widget配置变化,如:热修复

setState: 需要更新视图,主动调这个函数

五、原理

image.png

Widget、Element、RenderObject密不可分的关系

在探索构建、布局及绘制原理前,需要先了解Widget、Element、RenderObject的原理及相互关系。Widget会创建自己的Element和RenderObject(并不是每个Widget都有RenderObject,如statefulWidget、statelessWidget),其中Element持有Widget和RenderObject两者的引用;开发者面向的只有Widget,其中Widget是不可变的,Element、RenderObject是可变的,正是这样大大提高的Flutter的性能。

可以理解Widget只是配置信息,实际重点工作都在Element中进行,也就是build阶段,而RenderObject负责布局及绘制的工作;打个比方,Widget是战略部署人员,他只负责部署战略,当一套战略部署需要修改的时候,并不会在原有基础上修改,而是再次制定新的方案,制定完成后将该方案交给实施方案的负责人(Element),此时负责人将新方案与旧的方案加以比较,修改变动点,将具体的方案流程交给(RenderObject)去实现。

再看一下官方的一个例子:

image.png

首先Recanle green Widget下面有一个子Widget Circle blue,绿色组件创建一个Element,再创建一个RenderObject,Element同时持有两者的引用;接下来蓝色组件创建一个Element,并将其挂在到父Element上,再创建一个RenderObject,attach到了父RenderObjuect的插槽,此时渲Render tree建立。

Element负责build阶段,接下来看下Element Tree,Element构建了Element Tree,它的职责就是维护这棵树,可以理解Element Tree是一个“虚拟DOM”,由于DOM每次更新操作都会重新渲染整个DOM,非常耗性能,所以出现了虚拟DOM的概念,也就是通过diff算法,只更新改变的元素就好,大大提升了效率,Element Tree也在flutter中扮演了这样的角色,如statefulWidget通过state.setState通知Element改变,Element对需要更新的Widget标记为dirty状态(被标记dirty的Element会加到dirty list中),表示这个Element需要被重建。

RenderObject负责渲染,在build后,开始布局及绘制(这里涉及到约束布局的概念,下面会说一下),之后生成适量描述数据,这部分就是RenderObject的工作。接下来就是上面提到过的光栅化及Skia处理后送往GPU。

布局约束
image.png

Flutter是盒子约束模型,上图中的每个节点都是RenderObject,父节点会将约束传达给下面的所有子节点,如最大最小宽高;子节点会依据约束定义具体size,将具体的size,如width:200、height:200,告诉父节点一直传给顶部。

你可能感兴趣的:(Flutter框架原理探索)