Flutter 的方式,实际上的渲染过程不依赖于原生,而是通过 C/C++编写的 Skia 渲染引擎完成界面渲染的。绘制界面的Dart 代码会被编译成原生代码,但是使用的是 Skia 完成渲染。Flutter 内置了 Skia 渲染引擎,使得即便是用户的手机没有更新到最新版本的手机操作系统也能够保持最新的渲染性能。
执行Flutter引擎中图形相关代码(Skia),这个线程通过与GPU通信,获取Layer Tree并执行栅格化以及合成上屏等操作,将Layer Tree显示在屏幕上。

Flutter渲染机制在UI线程执行到compositeFrame()过程经过多层调用,将栅格化的任务Post到GPU线程来执行。GPU线程一旦空闲则会执行Rasterizer的draw()操作。图中LayerTree::Paint()过程是一个比较重要的操作,会嵌套调用不同layer的Paint过程,比如TransformLayer,PhysicalShapeLayer,ClipRectLayer,PictureLayer等都执行完成会执行flush()将数据发送给GPU。

ClassSurface
三种不同的AndroidSurface,见小节2.6.3,说明如下:

LayerTree的root_layer来源于SceneBuilder过程初始化,第一个调用PushLayer()的layer便成为root_layer_,后面的调用会形成一个树状结构。从上图,可知ContainerLayer共有9个子类,由这些子类组合成为了一个layer tree,具体的组合方式取决于业务使用方,在LayerTree的Prepoll和Paint过程便会调用这些layer的方法,下面来看看这9个类:
源码角度来看看Flutter的渲染绘制机制,跟渲染直接相关的两个线程是UI线程和GPU线程:
通过VSYNC信号使UI线程和GPU线程有条不紊的周期性的渲染界面,本文介绍VSYNC的产生过程、UI线程在引擎和框架的绘制工作。

当需要渲染则会调用到Engine的ScheduleFrame()来注册VSYNC信号回调,一旦触发回调doFrame()执行完成后,便会移除回调方法,也就是说一次注册一次回调;
当需要再次绘制则需要重新调用到ScheduleFrame()方法,该方法的唯一重要参数regenerate_layer_tree决定在帧绘制过程是否需要重新生成layer tree,还是直接复用上一次的layer tree;
UI线程的绘制过程,最核心的是执行WidgetsBinding的drawFrame()方法,然后会创建layer tree视图树
再交由GPU Task Runner将layer tree提供的信息转化为平台可执行的GPU指令。

Embedder中存在四个Runner,四个Runner分别如下。其中每个Flutter Engine各自对应一个UI Runner、GPU Runner、IO Runner,但所有Engine共享一个Platform Runner。




GPU Runner并不直接负责渲染操作,其负责GPU相关的管理和调度。当layer tree信息到来时,GPU Runner将其提交给指定的渲染平台,渲染平台是Skia配置的,不同平台可能有不同的实现。
GPU Runner相对比较独立,除了Embedder外其他线程均不可向其提交渲染信息。
本文结合Flutter的官方描绘的框架和渲染流程,简要介绍了渲染的过程实现方式,让读者对Flutter在渲染方面有基本的理解,便于以后的开发和探索。为Flutter生态作出一点自己的贡献,期待Flutter越来越好!