Rendering
Flutter
的渲染管道是由多个阶段构成的:
- 1,处理用户输入事件,例如 手势,键盘,或者触摸屏幕等等。
- 2,运行动画。
- 3,构建
Widget
树。 - 4,对
RendObject
进行布局。 - 5,对
RendObject
进行绘制。 - 6,进行视图合成。
- 7,将合成的视图,合成一张图片。
build
当 Widget树
中的Widget
接收到用户输入事件或Animation
时,Flutter 就会进入构建阶段
。在构建阶段
,会重新构建Widget Tree
,会更新Element Tree
和Render Tree
。
layout
RenderObject
负责布局和绘制,在layout
阶段,沿着Render Tree
,向下传递约束信息
大多数的Widget
使用的是BoxConstraint
,是一个二维坐标的约束。
具体的渲染实例是 RenderBox
,子渲染对象根据父渲染对象的约束,决定其自身的大小,并传递给其父渲染对象。
paint
在布局阶段结束后,就进入了绘制阶段。RanderObject,在画布(canvas)中,可以通过重写paint()
方法,使用drawRect
或drawLine
来自己绘制。 如果还有子对象,可以使用paintChild()
来绘制子RenderObject
。
compositing
在合成阶段,会将多个图片合成一个总图,但是为什么要进行合成呢?那是因为在绘制阶段,会在多个不同的画布中绘制。
为什么要在多个不同的画布中绘制呢?当我们在Scroll
中进行滑动时,我们不需要更新文本内容,只需要更新滚动条,重新定位文本即可。
为了解决多个画布绘制的问题,Flutter使用了另外一个树layer Tree
,它保存每个layer
所需要的绘制操作。
每个Layer
的绘制,都是各自分离的,Flutter
会尝试将多个RenderObject
归入同一Layer
。如果使用 RepaintBoundary()
来包装一个Widget
,Flutter
会给它单独的一个Layer
,这样可以避免额外绘制。
Rasterize
最后,将合成的图层,送到flutter 引擎
,转化为像素信息,这个过程叫做栅格化
,由GPU进行展示。如果图层的内容不变的话,引擎会重用这些像素,如果有许多不必要的重绘时,可以使用RepaintBoundary()
。创建一个单独的图层,对于性能来说,是一个很好的策略。