解码Flutter(二)Flutter渲染

256 阅读2分钟

Rendering

Flutter的渲染管道是由多个阶段构成的:

截屏2022-05-04 下午5.22.47.png

  • 1,处理用户输入事件,例如 手势,键盘,或者触摸屏幕等等。
  • 2,运行动画。
  • 3,构建Widget树。
  • 4,对RendObject进行布局。
  • 5,对RendObject进行绘制。
  • 6,进行视图合成。
  • 7,将合成的视图,合成一张图片。

build

Widget树中的Widget接收到用户输入事件或Animation时,Flutter 就会进入构建阶段。在构建阶段,会重新构建Widget Tree,会更新Element TreeRender Tree

飞书20220504-181949.jpg

layout

RenderObject负责布局和绘制,在layout阶段,沿着Render Tree,向下传递约束信息

截屏2022-05-04 下午6.24.59.png

大多数的Widget使用的是BoxConstraint,是一个二维坐标的约束。

具体的渲染实例是 RenderBox,子渲染对象根据父渲染对象的约束,决定其自身的大小,并传递给其父渲染对象。

截屏2022-05-04 下午5.24.43.png

paint

在布局阶段结束后,就进入了绘制阶段。RanderObject,在画布(canvas)中,可以通过重写paint()方法,使用drawRectdrawLine 来自己绘制。 如果还有子对象,可以使用paintChild()来绘制子RenderObject

截屏2022-05-04 下午6.51.28.png

compositing

在合成阶段,会将多个图片合成一个总图,但是为什么要进行合成呢?那是因为在绘制阶段,会在多个不同的画布中绘制。

为什么要在多个不同的画布中绘制呢?当我们在Scroll中进行滑动时,我们不需要更新文本内容,只需要更新滚动条,重新定位文本即可。

为了解决多个画布绘制的问题,Flutter使用了另外一个树layer Tree,它保存每个layer所需要的绘制操作。

截屏2022-05-04 下午7.29.15.png

每个Layer的绘制,都是各自分离的,Flutter会尝试将多个RenderObject归入同一Layer。如果使用 RepaintBoundary()来包装一个WidgetFlutter会给它单独的一个Layer,这样可以避免额外绘制。

Rasterize

最后,将合成的图层,送到flutter 引擎,转化为像素信息,这个过程叫做栅格化,由GPU进行展示。如果图层的内容不变的话,引擎会重用这些像素,如果有许多不必要的重绘时,可以使用RepaintBoundary()。创建一个单独的图层,对于性能来说,是一个很好的策略。