flutter widget、Element、 RenderObject

注:rebulild、layout、paint都是在drawFrame過程中完成的

https://juejin.im/post/5b9a7d396fb9a05d3154fa5a

build.png

flutter_rebuild.png

update child Element的時候的child widget,有時候是要this widget的build方法得到的,有時候直接this widget 的 child屬性獲取,不同的widget不一樣

widget_element.png

inflateWidget方法的作用就是創(chuàng)建widget對應(yīng)的element

  • Widget實際上就是Element的配置數(shù)據(jù),Widget樹實際上是一個配置樹,而真正的UI渲染樹是由Element(或者確切說是由RenderObject)構(gòu)成;不過,由于Element是通過Widget生成,所以它們之間有對應(yīng)關(guān)系,所以在大多數(shù)場景,我們可以寬泛地認為Widget樹就是指UI控件樹或UI渲染樹。

  • 一個Widget對象可以對應(yīng)多個Element對象。這很好理解,根據(jù)同一份配置(Widget),可以創(chuàng)建多個實例(Element)。

  • 從創(chuàng)建到渲染的大體流程是:根據(jù)Widget生成Element,然后創(chuàng)建相應(yīng)的RenderObject并關(guān)聯(lián)到Element.renderObject屬性上,最后再通過RenderObject來完成布局排列和繪制。

flutter使用RenderObjects管理傳統(tǒng)UI對象的許多職責(zé)(例如維護布局的狀態(tài))。RenderObjects在幀之間保持不變,flutter的輕量級Widgets告訴框架在狀態(tài)之間改變RenderObjects。
widget和element一一對應(yīng),但是不是所有element都有renderObject。如下代碼所示,如果Element不是 RenderObjectElement,則使用的是子樹中的element的renderObject??衫斫鉃樘峁﹍ayout或paint相關(guān)數(shù)據(jù)的widget/element自身并不代表一塊UI,其是為子控件提供參數(shù)的,所以獲取子樹中的renderObject,通過parentData或者其他方式影響子樹中的renderObject的layout/paint。

//Element class
RenderObject get renderObject {
    RenderObject result;
    void visit(Element element) {
      assert(result == null); // this verifies that there's only one child
      if (element is RenderObjectElement)
        result = element.renderObject;
      else
        element.visitChildren(visit);
    }
    visit(this);
    return result;
  }

Layer

iOS的每一個UIView都有一個layer,flutter的render object不一定存在layer,一般情況下一個renderObject子樹都渲染在一個layer上,那么什么renderObject具有l(wèi)ayer,子renderObject怎么渲染到這個layer?

  • 當(dāng)一個renderObject的 alwaysNeedsCompositing == true 或者isRepaintBoundary == true,renderOject會有對應(yīng)的compositing layer
  • 子renderObject會對目標layer返回對應(yīng)的offsetLayer, 目標compositing layer再根據(jù)offset合成一個渲染的紋理buffer

flutter框架的四層封裝

WeChatae36f7d5e8778ecb69909ac3079f3031.png
  • dart:ui是最后一個Dart層,它基本上處理與Flutter引擎的通信。
  • 大多數(shù)時候你會發(fā)現(xiàn)Flutter使用的是一個RenderBox而不是RenderObject,RenderObject中沒有坐標系統(tǒng)。這是因為項目背后的人們意識到一個簡單的盒子布局協(xié)議非常適合構(gòu)建高性能的UI。想想放在它自己的盒子里的每個小部件,這個盒子被計算出來,然后與其他預(yù)先布置好的盒子一起排列。因此,如果布局中只有一個窗口小部件發(fā)生更改(例如按鈕或開關(guān)),則系統(tǒng)只需要重新計算這個相對較小的盒子。
  • element持有對Widget和RenderObject.RenderObject負責(zé)布局,繪畫和交互處理,實例化非常昂貴。element是不可變Widget樹和可變RenderObject樹之間的粘合劑。Elements主要是對象,它們非常擅長將兩個對象相互比較

State的生命周期

  • initState
  • didChangeDependencies
  • didUpdateWidget
  • build
  • deactivate
  • dispose
State生命周期.png
剛進入頁面
  • initState
  • didChangeDependencies
  • build
退出頁面
  • deactivate
  • dispose
deactivate
# StatefulElement
@override
  void deactivate() {
    _state.deactivate();
    super.deactivate();
  }
# Element
void deactivateChild(Element child) {
...
    owner._inactiveElements.add(child); // this eventually calls child.deactivate()
...

# BuildOwner
final _InactiveElements _inactiveElements = _InactiveElements();
void add(Element element) {
   ...
    if (element._active)
      _deactivateRecursively(element);
...
}

static void _deactivateRecursively(Element element) {
   ...
    element.deactivate();
    ...
  }

flutter熱重載

flutter熱重載會執(zhí)行reassemble方法,主要流程如下


reassemble.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容