前面介紹了flutter如何布局後,我們接著來了解flutter式如何將widget呈現在我們的裝置畫面上
首先,先簡單介紹flutter是如何生成我們每一frame。我們透過drawFrame()來pump我們的構建和渲染管道來生成我們的每一個frame,並且事由handleDrawFrame所調用:
而每一個frame都是藉由以下階段組成
1.Animation phase: 按註冊順序調用scheduleFrameCallback
註冊的所有transient frame後回調
2.Microtasks: 在handleBeginFrame
返回後,任何由transient frame回調調度的微任務都將開始運行。之後,調用[PlatformDispatcher.onDrawFrame]註冊的handleDrawFrame
,它會調用所有的persistent frame回調,其中包括drawFrame()方法
2-1.Build phase: 重新構建widget tree中所有dirty的Element
2-2.Layout phase: 系統中所有dirty的RenderObject
都被佈局
2-3.Compositing bits phase: 任何dirty的RenderObject對像上的compositing bits都會更新
2-4.Paint phase: 系統中所有dirty的RenderObject都被重新繪製,並且生成Layer Tree
2-5.Compositing phase: 將Layer Tree變成Scene
並發送到GPU
2-6.Semantics phase: 系統中所有dirty的RenderObject都更新了它們的語義
3.Finalization phase in the widgets layer: Widgets tree已經finalized,並造成在本幀(frame)從widget tree中刪除的任何對像上調用
4.Finalization phase in the scheduler layer: drawFrame
返回後,handleDrawFrame
調用幀後回調
今天我們來簡單的了解build構建的原理過程,首先我們從flutter官方上可以看到:
link
Flutter中的Widget樹根據Element樹生成,Render樹則是透過Element樹產生,也就是:
scheduleAttachRootWidget
1.StatelessWidget、StatefulWidget...等等Widgets所組成的Widget Tree會透過flutter轉換為Element tree。
Element tree分為ComponentElement
、RenderObjectElement
,其中:
2.當在構建階段,Flutter會為element tree中的每個RenderObjectElement
創建或更新一個繼承自RenderObject的對象。
RenderObject是base class,其中
並且渲染的widget,大多是繼承自RenderBox subclass
該子類表示2D笛卡爾座標下固定大小的RenderObject。RenderBox提供了盒子約束模型的基礎,為每個要渲染的小部件建立最小和最大寬度和高度
也就是flutter構建樹的過程就是:
1.flutter調用runApp()中的scheduleAttachRootWidget
,並調用來進行樹構建(會構建Widget Tree,Element Tree與RenderObject Tree三棵樹)
2.並調用attachToRenderTree
來inflate這個widget並實際將生成的RenderObject
並設置為container的子級:
我們能看到createElement方法創建來element(RenderObjectToWidgetElement),他是一個RootRenderObjectElement,也就是root element
element!.mount(null, null)
會向下遍歷並構建整個widget樹
3.然後再調用這個updateChild方法並調用inflateWidget
去創建這個子Widget對應的Element
...
4.再調用他的mount方法去調用子widget的build方法去返回他的子子widget
5.重複循環直到這個Element是RenderObjectElement
6.最後,在通過attachToRenderTree創建Render Tree
今天簡單的講解樹構建的流程,在這裡我們的樹已經構建起來,明天在簡單的介紹渲染過程。