深刻淺出 Flutter Framework 之 Layer

本文是『 深刻淺出 Flutter Framework 』系列文章的第五篇,對 Layer 的類層級結構以及 Layer 的狀態管理進行了簡要的分析介紹。git

本文同時發表於個人我的博客github

本系列文章將深刻 Flutter Framework 內部逐步去分析其核心概念和流程,主要包括:markdown

Overview


前面的文章中咱們介紹過在 Flutter build、layout、render 過程當中會生成 3 棵樹:ide

  • Element Tree
  • RenderObject Tree
  • Layer Tree

能夠說 Layer Tree 是 Flutter Framework 最終的輸出產物,以後的流程就進入到 Flutter Engine 了。 如上圖:oop

分類


如上圖,Layer是抽象基類,其內部實現了基本的 Layer Tree 的管理邏輯以及對渲染結果複用的控制邏輯。 具體的 Layer 大體能夠分爲2類:post

  • Container Layer:正如其名,做爲 Layer 容器,用於管理一組 Layers,是惟一能夠擁有 child layer 的 Layer;
  • 非 Container Layer:真正用於承載渲染結果的 layer,在 Layer Tree 中屬於葉結點,如:PictureLayer承載的是圖片的渲染結果,TextureLayer承載的是紋理的渲染結果。

狀態管理


抽象基類Layer一個很是重要的職責就是管理 Layer Tree 的狀態 簡單講,就是控制什麼狀況下能夠複用 engine 在前一幀渲染的結果,什麼狀況下須要刷新,即須要 engine 從新渲染。固然,這是出於性能考慮,避免因沒必要要的渲染操做而浪費資源。性能

EngineLayer

每一個 Layer 實例都有一個與之對應的EngineLayer實例,其屬於 engine 層範疇,對 framework 來講是個黑盒。能夠簡單理解 EngineLayer 爲 engine 渲染的結果。ui

深刻淺出 Flutter Framework 之 PaintingContext 一文中介紹過的SceneBuilder類有一系列的push方法 (如:pushOffsetpushClipRect等),這些方法的返回值即爲EngineLayer實例。this

如:ColorFilterLayer#addToScene方法在調用SceneBuilder#pushColorFilter方法時就保存了其返回的engineLayerspa

@override
  void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]) {
    engineLayer = builder.pushColorFilter(colorFilter, oldLayer: _engineLayer);
    addChildrenToScene(builder, layerOffset);
    builder.pop();
  }
複製代碼

needsAddToScene

咱們知道,Layer上的內容須要藉助SceneBuilder生成Scene,以後才能被渲染在屏幕上。 這一過程被稱之爲addToScene

Layer內有一個很是重要的變量:_needsAddToScene,用於記錄該 Layer 自上次渲染後(addToScene)是否發生了變化。 即,該 layer 背後的 EngineLayer 是否能夠複用。

Whether this layer has any changes since its last call to [addToScene].

Layer剛初始化時,_needsAddToScenetrue,在第一次調用addToScene後置爲false,以後有幾種狀況可能會被再次置爲true,代表該 layer須要 engine 從新渲染,以下圖所示:

  • 自身發生了變化,如PictureLayer#pictureTransformLayer#transform被從新賦值;
  • 子節點有增刪;
  • 子節點的needsAddToScene變爲true

Layer#alwaysNeedsAddToScenetrue時,表示該 layer 在每幀刷新時都須要從新渲染。其對_needsAddToScene的影響以下:

@protected
  @visibleForTesting
  void updateSubtreeNeedsAddToScene() {
    _needsAddToScene = _needsAddToScene || alwaysNeedsAddToScene;
  }
複製代碼

addToScene

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()方法中,當_ needsAddToScenefalse_engineLayer!=nil時直接複用上次的渲染結果。

好了,今天就先到這裏了!

相關文章
相關標籤/搜索