参考
从架构到源码:一文了解Flutter渲染机制_阿里技术-CSDN博客
每帧的处理过程
我们知道Android上的渲染都是在VSync信号驱动下进行的,Flutter在Android上的渲染也不例外,它会向Android系统注册并等待VSync信号,等到VSync信号到来以后,调用沿着C++ Engine->Java Engine,到达Dart Framework,开始执行Dart代码,经历Layout、Paint等过程,生成一棵Layer Tree,将绘制指令保存在Layer中,接着进行栅格化和合成上屏。
1)向Android系统注册并等待VSync信号
Flutter引擎启动时,会向Android系统的Choreographer(管理VSync信号的类)注册并接收VSync信号的回调。
2)接收到VSync信号,通过C++ Engine向Dart Framework发起渲染调用
当VSync信号产生以后,Flutter注册的回调被调用,VsyncWaiter::fireCallback() 方法被调用,接着会执行 Animator::BeiginFrame(),最终调用到 Window::BeginFrame() 方法,WIndow实例是连接底层Engine和Dart Framework的重要桥梁,基本上与平台相关的操作都会通过Window实例来连接,例如input事件、渲染、无障碍等。
3)Dart Framework开始在UI线程执行渲染逻辑,生成Layer Tree,并将栅格化任务post到GPU线程执行
Window::BeiginFrame() 接着调用,执行到 RenderBinding::drawFrame() 方法,这个方法会去驱动UI界面上的dirty节点(需要重绘的节点)进行重新布局和绘制,如果渲染过程中遇到图片,会先放到Worker Thead去加载和解码,然后再放到IO Thread生成图片纹理,由于IO Thread和GPI Thread共享EGContext,因此IO Thread生成的图片纹理可以被GPU Thread直接访问。
4)GPU线程接收到Layer Tree,进行栅格化以及合成上屏的工作
Dart Framework绘制完成以后会生成绘制指令保存在Layer Tree中,通过 Animator::RenderFrame() 把Layer Tree提交给GPU Thread,GPU Thread接着执行栅格化和上屏显示。之后通过 Animator::RequestFrame() 请求接收系统的下一次VSync信号,如此循环往复,驱动UI界面不断更新。
每帧都包含如下步骤:
The animation phase:
此阶段又叫SchedulerPhase.transientCallbacks。
Window.onBeginFrame上注册的监听方法SchedulerBinding.handleBeginFrame,会被engine调用来准备framework来去产生一个新帧。
在handleBeginFrame中,会按顺序执行 在SchedulerBinding.scheduleFrameCallback()方法中注册的所有callback,这包括驱动AnimationController对象的所有Ticker实例,这意味着所有active动画对象都在这一点启动。
之所以叫transientCallbacks,是因为只会把注册的callback执行一次,之后就全部丢弃。
Microtasks:
此阶段又叫SchedulerPhase.midFrameMicrotasks
handleBeginFrame 返回后,所有的microtasks(在callback中调度的)开始运行,This typically includes callbacks for futures from Tickers and AnimationControllers that completed this frame.
persistentCallbacks
此阶段又叫SchedulerPhase.persistentCallbacks,
接着就是调用Window.onDrawFrame上注册的监听方法SchedulerBinding.handleDrawFrame,该调用将调用所有注册persistentCallbacks,
之所以叫persistentCallbacks是因为每帧都会执行,执行完后不会删除persistentCallbacks列表。
其中最引人注目的是此方法RendererBinding.drawFrame,其过程如下:
For more details, see PipelineOwner.
The build phase:
这个阶段是WidgetsBinding的drawFrame中的。WidgetsBinding 继承了SchedulerBinding。
if (renderViewElement != null) buildOwner.buildScope(renderViewElement); super.drawFrame();
Althe dirty Elements in the widget tree are rebuilt (see State.build).
See State.setState for further details on marking a widget dirty for building.
See BuildOwner for more information on this step.
The layout phase:
Althe dirty RenderObjects in the system are laid out (see RenderObject.performLayout).
See RenderObject.markNeedsLayout for further details on marking an object dirty for layout.
The compositing bits phase:
The compositing bits on any dirty RenderObject objects are updated.
See RenderObject.markNeedsCompositingBitsUpdate.
The paint phase:
Althe dirty RenderObjects in the system are repainted (see RenderObject.paint).
This generates the Layer tree.
See RenderObject.markNeedsPaint for further details on marking an object dirty for paint.
The compositing phase:
The layer tree is turned into a Scene and sent to the GPU.
The semantics phase:
Althe dirty RenderObjects in the system have their semantics updated.
This generates the SemanticsNode tree.
See RenderObject.markNeedsSemanticsUpdate for further details on marking an object dirty for semantics.
The finalization phase:
此阶段又叫SchedulerPhase.postFrameCallbacks,
The finalization phase in the widgets layer:
在WidgetsBinding.drawFrame中执行完super.drawFrame后,会调用:
buildOwner.finalizeTree();
The widgets tree is finalized.
This causes State.dispose to be invoked on any objects that were removed from the widgets tree this frame.
The finalization phase in the scheduler layer:
在persistentCallbacks执行之后,SchedulerBinding.handleDrawFrame 会去调用在addPostFrameCallback()注册的postFrameCallbacks。