经过Build、Layout、Paint后,Render Tree变成Layer Tree,那么Layer Tree是如何合成,以变成最终的渲染数据呢?这就是Composition过程。
Mark阶段
Framework使用_neesaAddToScene字段标识当前图层是否需要进行合成,通常当一个Layer节点有子节点的变化(adoptChild、dropChild)或者Layer节点本身有变化时,需要将该标识设置为true,表示当前图层发生改变,需要重新合成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Layer { set alpha(int? value) { if (value != _alpha) { if (value == 255 || _alpha == 255) { engineLayer = null; } _alpha = value; markNeedsAddToScene(); } }
set elevation(double? value) { if (value != _elevation) { _elevation = value; markNeedsAddToScene(); } }
void markNeedsAddToScene() { if (_needsAddToScene) { return; } _needsAddToScene = true; }
}
|
Flush阶段
合成的Flush阶段是从renderView.compositeFrame方法开始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| class RenderView { void compositeFrame() { try { final ui.SceneBuilder builder = ui.SceneBuilder(); final ui.Scene scene = layer!.buildScene(builder); if (automaticSystemUiAdjustment) { _updateSystemChrome(); } _view.render(scene); scene.dispose(); } finally { } } }
class ContainerLayer { ui.Scene buildScene(ui.SceneBuilder builder) { updateSubtreeNeedsAddToScene(); addToScene(builder); if (subtreeHasCompositionCallbacks) { _fireCompositionCallbacks(includeChildren: true); } _needsAddToScene = false; final ui.Scene scene = builder.build(); return scene; }
void updateSubtreeNeedsAddToScene() { super.updateSubtreeNeedsAddToScene(); Layer? child = firstChild; while (child != null) { child.updateSubtreeNeedsAddToScene(); _needsAddToScene = _needsAddToScene || child._needsAddToScene; child = child.nextSibling; } }
void addToScene(ui.SceneBuilder builder) { addChildrenToScene(builder); }
void addChildrenToScene(ui.SceneBuilder builder) { Layer? child = firstChild; while (child != null) { child._addToSceneWithRetainedRendering(builder); child = child.nextSibling; } } }
class Layer { void _addToSceneWithRetainedRendering(ui.SceneBuilder builder) { if (!_needsAddToScene && _engineLayer != null) { builder.addRetained(_engineLayer!); return; } addToScene(builder); _needsAddToScene = false; } }
|