iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
自我挑戰組

30天學習flutter系列 第 10

10.flutter的布局(三)

  • 分享至 

  • xImage
  •  

前面介紹了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
https://ithelp.ithome.com.tw/upload/images/20220925/20108931SwJxUchDZx.png

Flutter中的Widget樹根據Element樹生成,Render樹則是透過Element樹產生,也就是:
scheduleAttachRootWidget
1.StatelessWidget、StatefulWidget...等等Widgets所組成的Widget Tree會透過flutter轉換為Element tree。

Element tree分為ComponentElementRenderObjectElement,其中:

  • ComponentElement: 其他elements的host (ComponentElement主要有兩個子類StatelessElement和StatefulElement)
  • RenderObjectElement: 參與佈局或繪製階段的element* (只有RenderObject的對象及其子類才有Layout的過程)

2.當在構建階段,Flutter會為element tree中的每個RenderObjectElement創建或更新一個繼承自RenderObject的對象

RenderObject是base class,其中

  • RenderParagraph渲染文本
  • RenderImage 渲染圖像
  • RenderTransform在繪製其子對象之前應用轉換

並且渲染的widget,大多是繼承自RenderBox subclass

該子類表示2D笛卡爾座標下固定大小的RenderObject。RenderBox提供了盒子約束模型的基礎,為每個要渲染的小部件建立最小和最大寬度和高度

也就是flutter構建樹的過程就是:

1.flutter調用runApp()中的scheduleAttachRootWidget,並調用來進行樹構建(會構建Widget Tree,Element Tree與RenderObject Tree三棵樹)
https://ithelp.ithome.com.tw/upload/images/20220925/20108931hb4cUR3zHR.png
https://ithelp.ithome.com.tw/upload/images/20220925/20108931Qw5zipZCHa.png

https://ithelp.ithome.com.tw/upload/images/20220925/20108931Sba9qNh7XC.png

2.並調用attachToRenderTree來inflate這個widget並實際將生成的RenderObject並設置為container的子級:
https://ithelp.ithome.com.tw/upload/images/20220925/20108931Otcbh6gsub.png

我們能看到createElement方法創建來element(RenderObjectToWidgetElement),他是一個RootRenderObjectElement,也就是root element

element!.mount(null, null)會向下遍歷並構建整個widget樹
https://ithelp.ithome.com.tw/upload/images/20220925/20108931PdUfISlFWq.png
https://ithelp.ithome.com.tw/upload/images/20220925/201089316GCrumAD0l.png

3.然後再調用這個updateChild方法並調用inflateWidget去創建這個子Widget對應的Element

https://ithelp.ithome.com.tw/upload/images/20220925/20108931EiHOAT5zfj.png
...
https://ithelp.ithome.com.tw/upload/images/20220925/20108931bGe2KOAlbI.png

4.再調用他的mount方法去調用子widget的build方法去返回他的子子widget

5.重複循環直到這個Element是RenderObjectElement

6.最後,在通過attachToRenderTree創建Render Tree


今天簡單的講解樹構建的流程,在這裡我們的樹已經構建起來,明天在簡單的介紹渲染過程。


上一篇
9.flutter的布局(二)
下一篇
11.flutter的布局(四)
系列文
30天學習flutter30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言