本文是『 深刻浅出 Flutter Framework 』系列文章的第五篇,对 Layer 的类层级结构以及 Layer 的状态管理进行了简要的分析介绍。git
本文同时发表于个人我的博客github
本系列文章将深刻 Flutter Framework 内部逐步去分析其核心概念和流程,主要包括:markdown
前面的文章中咱们介绍过在 Flutter build、layout、render 过程当中会生成 3 棵树:ide
能够说 Layer Tree 是 Flutter Framework 最终的输出产物,以后的流程就进入到 Flutter Engine 了。 如上图:oop
build
过程当中,由 Element Tree 生成 RenderObject Tree (在 深刻浅出 Flutter Framework 之 Element 一文中介绍过只有 RenderObject_Element 才会有对应的 RenderObject)paint
阶段,由 RenderObject Tree 生成 Layer Tree (在 深刻浅出 Flutter Framework 之 PaintingContext 一文中介绍过只有当RenderObject#isRepaintBoundary
为true
时才会生成独立的 Layer 节点) 如上图,
Layer
是抽象基类,其内部实现了基本的 Layer Tree 的管理逻辑以及对渲染结果复用的控制逻辑。 具体的 Layer 大体能够分为2类:post
PictureLayer
承载的是图片的渲染结果,TextureLayer
承载的是纹理的渲染结果。抽象基类Layer
一个很是重要的职责就是管理 Layer Tree 的状态 简单讲,就是控制什么状况下能够复用 engine 在前一帧渲染的结果,什么状况下须要刷新,即须要 engine 从新渲染。固然,这是出于性能考虑,避免因没必要要的渲染操做而浪费资源。性能
每一个 Layer 实例都有一个与之对应的EngineLayer
实例,其属于 engine 层范畴,对 framework 来讲是个黑盒。能够简单理解 EngineLayer 为 engine 渲染的结果。ui
在 深刻浅出 Flutter Framework 之 PaintingContext 一文中介绍过的SceneBuilder
类有一系列的push
方法 (如:pushOffset
、pushClipRect
等),这些方法的返回值即为EngineLayer
实例。this
如:ColorFilterLayer#addToScene
方法在调用SceneBuilder#pushColorFilter
方法时就保存了其返回的engineLayer
:spa
@override
void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]) {
engineLayer = builder.pushColorFilter(colorFilter, oldLayer: _engineLayer);
addChildrenToScene(builder, layerOffset);
builder.pop();
}
复制代码
咱们知道,Layer上的内容须要借助SceneBuilder
生成Scene
,以后才能被渲染在屏幕上。 这一过程被称之为addToScene
。
在Layer
内有一个很是重要的变量:_needsAddToScene
,用于记录该 Layer 自上次渲染后(addToScene
)是否发生了变化。 即,该 layer 背后的 EngineLayer 是否能够复用。
Whether this layer has any changes since its last call to [addToScene].
在Layer
刚初始化时,_needsAddToScene
为true
,在第一次调用addToScene
后置为false
,以后有几种状况可能会被再次置为true
,代表该 layer须要 engine 从新渲染,以下图所示:
PictureLayer#picture
、TransformLayer#transform
被从新赋值;needsAddToScene
变为true
;
Layer#alwaysNeedsAddToScene
为true
时,表示该 layer 在每帧刷新时都须要从新渲染。其对_needsAddToScene
的影响以下:
@protected
@visibleForTesting
void updateSubtreeNeedsAddToScene() {
_needsAddToScene = _needsAddToScene || alwaysNeedsAddToScene;
}
复制代码
addToScene
方法能够说是Layer
中最重要的方法之一,用于将 layer 送入 engin 进行渲染。 由具体的子类去实现该方法,Container 类型的 Layer 与非 Container 类型的 Layer 在实现上仍是有较大区别,细节在此再也不赘述,感兴趣的同窗能够看看源码。
如上面这张长长的图,如今要描述的一切都始于RenderView.compositeFrame()
:
RenderView 是 RenderObject Tree 的根节点,在每帧刷新时都会调用其
compositeFrame
方法去合成新的帧 RenderView 对应的 Layer 是ContainerLayer
几个关键点:
ContainerLayer.buildScene()
方法首先去更新needsAddToScene
标志位 (对 Layer Tree 进行深度遍历),子节点的值会影响父节点 (子节点有更新时,父节点确定也要刷新);ContainerLayer.addToScene()
方法,该方法会对子节点进行递归操做;ContainerLayer._addToSceneWithRetainedRendering()
方法中,当_ needsAddToScene
为false
且_engineLayer!=nil
时直接复用上次的渲染结果。好了,今天就先到这里了!