本文是『 深刻淺出 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
時直接複用上次的渲染結果。好了,今天就先到這裏了!