architectural-overview 参考一些图片
Flutter’s rendering model
传统的APP绘制方案
- APP调用java写的Android framework层的代码,(TextView、EditText)
- Android系统库提供组件,将组件自身绘制到Canvas对象上。
- 通过Skia进行绘制(最早是OpenGL ES)
- Skia是C/C++写的 graphic engine,调用CPU或GPU去进行绘制
一般跨平台方案(如ReactNative)
- 在Android、IOS的UI库上抽象一层,提供统一的绘制 API
- 用解释型语言 (JavasScript)描述,和基于 Java、Object-C 的系统库交互
- 说人话就是 抽取一个中间层,中间层下面是 Android、IOS的本地UI库
- 效率不高 (相当于在传统APP上,再加了个中间层。)
Flutter的方案
- Flutter与一般方案相反,使用自己 UI库
- 直接将Dart编译成native code(C、C++),使用Skia 渲染引擎去绘制 (相当与干了Android FrameWork中 TextView等的操作)
- Flutter在Engine中嵌入了Skia,允许用户使用Skia最新新能,即便平台没更新自己的Skia库
- 说人话就是 抽取一个中间层,中间层下面是 Android、IOS的图像引擎
- 相当于在Android、IOS上 实现了一套FrameWork层的绘制代码
绘制的几个阶段
Build:Widget–>Element Tree
一个简单的代码片段,来展示一个简单的widget hierarchy(组件的树形结构)
Container(
color: Colors.blue,
child: Row(
children: [
Image.network('https://www.example.com/1.png'),
Text('A'),
],
),
);
- 当Flutter去渲染这个片段时,调用build() 方法。build返回相应的 widget,基于现在App state去绘制
- 在build阶段,build()引入了新的widget
- 上述代码,如果没有color,还会添加一个ColoredBox
if (color != null)
current = ColoredBox(color: color!, child: current);
Element
- Widget: Element == 1:1
- 可能根据 程序员布局,自动再生成一些Widget(例如 Iamge的RawImage)
- 可以被BuildContext,遍历查找
- RenderObjectElement, an element that participates in the layout or paint phases.
- 真正参与绘制(RawImage、RichText)
- 是Widget和RenderObject沟通的桥梁
- ComponentElement, a host for other elements.
- 外面的壳(Image\Text\Container)
Element Tree --> Render Tree
- RenderObjec: RenderTree的基础单元,layout and painting的抽象模型
- 每个RenderObject知道他的Parent,但对Child知之甚少,除了child的约束和如何访问。 以此使RenderObject足够抽象,来应付多种具体的case
- RenderObject 在Build期间为每个RenderObjectElement 创建或更新
- RenderObjects are primitives: RenderParagraph renders text, RenderImage renders an image, and RenderTransform applies a transformation before painting its child.
大多数Widget通过RenderBox的子类进行绘制,RenderBox抽象了 RenderObject在2D笛卡尔坐标拥有固定的Size。(最大、最小的宽高)
layout
- 在layout阶段,采用深度优先遍历,父-》子传递Constraint, 子-》父传递Size。
- 遍历结束每个RenderObject有了明确的Size,接下来 开始调用 paint() 方法,来进行Paint
paint
- 所有的RenderObject的root是RenderView,代表着 RenderTree的整体产出。
- 当平台需要新的Frame (Vsync,texture的 decompression/upload 完成),调用RenderTree的compositeFrame()方法
- 创建一个SceneBuilder 去创建、更新 Scene。
- 当Scene创建完成,RenderView传递Scene给Window.render()方法。 将控制交给GPU去渲染