flutter_5_深入_0_每帧的处理流程简介

参考

Flutter 是如何渲染的? (juejin.cn)

从架构到源码:一文了解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。

posted @ 2021-01-07 11:08  嘤嘤嘤123  阅读(384)  评论(0编辑  收藏  举报