Flutter框架原理探索

最近參與了Flutter項(xiàng)目模塊的開(kāi)發(fā)工作区宇,同時(shí)很好奇Flutter內(nèi)部的原理是什么,于是做了些研究议谷;Flutter是一種“響應(yīng)式框架”,與React類似芬首;開(kāi)發(fā)人員面向的是Widget,相當(dāng)于View衩辟,沒(méi)有Activity或者ViewController的概念;再深入探索昼钻,Widget其實(shí)只是負(fù)責(zé)配置數(shù)據(jù)封寞,真正的處理渲染是Element、RenderObject碗淌;在理解框架原理之后再使用Flutter確實(shí)會(huì)生動(dòng)很多抖锥。

一、框架

image.png

還是先從flutter的架構(gòu)入手纳像,它分為Framework層和Engine層兩部分拯勉,其中Framework用的是Dart語(yǔ)言,Engine是C++宫峦,可以理解為Engine是Framework和Android/iOS的橋梁;先來(lái)簡(jiǎn)單看一下犀勒,分析上面的架構(gòu)圖妥曲,F(xiàn)ramework層有兩種樣式規(guī)則Material(Android)、Cupertino(iOS)逾一,開(kāi)發(fā)人員只需關(guān)心Widgets(配置信息)遵堵,在內(nèi)部進(jìn)行渲染怨规,其中包括動(dòng)畫(huà)锡足、布局、繪制等舶得,將渲染后的圖層送入Engine,Engine包括Skia(渲染引擎)文字處理引擎等纫骑。

二九孩、渲染流水線

image.png

接下來(lái)看下它的渲染流水線,GPU發(fā)送Vsync(垂直同步信號(hào))通過(guò)Engine層煤墙,發(fā)送給Framework宪拥,F(xiàn)ramework接收到信號(hào)進(jìn)行動(dòng)畫(huà)、構(gòu)建设预、布局犁河、繪制順序依次進(jìn)行魄梯,最終渲染成Layer Tree 發(fā)給GPU;

那么GPU發(fā)送Vsync的時(shí)機(jī)是什么呢酿秸?其實(shí)在狀態(tài)發(fā)生變化的時(shí)候(比如調(diào)用State.setState()),此時(shí)Framework層會(huì)發(fā)送Vsync請(qǐng)求給Engine肝箱,Engine接收到后告知系統(tǒng)稀蟋,系統(tǒng)會(huì)發(fā)送Vsync信號(hào)再次通過(guò)Engine傳遞給Framework,F(xiàn)ramework接收到信號(hào)后進(jìn)行渲染骏融。

三、布局渲染

image.png

接上面怀泊,Render tree來(lái)負(fù)責(zé)布局渲染误趴,過(guò)程中需要繪制RenderObject所有子樹(shù),所以我們看到的界面是由很多l(xiāng)ayer組合成的凉当,也就是layer tree。渲染機(jī)制是這樣的糯而,由GPU發(fā)送Vsync信號(hào)泊窘,通知Framework更新一幀,在UI線程中通過(guò)build烘豹、layout和paint渲染成Layer Tree携悯,不過(guò)此時(shí)的渲染結(jié)果仍是矢量描述數(shù)據(jù),怎么做才能轉(zhuǎn)成讓用戶看得見(jiàn)的直觀視圖呢憔鬼?這就要Engine通過(guò)“光柵化”將矢量描述數(shù)據(jù)生成一個(gè)個(gè)的像素填充數(shù)據(jù);之后傳入GPU線程組合Layer Tree昌跌,由Skia渲染引擎渲染后送給GPU展示照雁。

四、State生命周期

image.png

State由Statefulwidget創(chuàng)建維護(hù)萍诱,這里說(shuō)一下污呼,Statefulewidget不是RenderObjectWidget,也就是它只有Elment沒(méi)有RenderObject燕酷,所以它不能渲染對(duì)象映企,它的職責(zé)是維護(hù)State,接下來(lái)看下State的生命周期堰氓。

initState:初始化

build:經(jīng)過(guò)初始化準(zhǔn)備好State后苹享,通過(guò)build構(gòu)建,如statelessWidget的build囤攀,StatefulWidget State的bulid

deactivate:State從視圖樹(shù)暫時(shí)刪除宫纬,如頁(yè)面跳轉(zhuǎn)切換

dispose:State從視圖樹(shù)永久移除

didiUpdateConfig:Widget配置變化,如:熱修復(fù)

setState: 需要更新視圖蝌衔,主動(dòng)調(diào)這個(gè)函數(shù)

五蝌蹂、原理

image.png

Widget噩斟、Element、RenderObject密不可分的關(guān)系

在探索構(gòu)建孤个、布局及繪制原理前剃允,需要先了解Widget、Element齐鲤、RenderObject的原理及相互關(guān)系斥废。Widget會(huì)創(chuàng)建自己的Element和RenderObject(并不是每個(gè)Widget都有RenderObject,如statefulWidget给郊、statelessWidget)牡肉,其中Element持有Widget和RenderObject兩者的引用;開(kāi)發(fā)者面向的只有Widget丑罪,其中Widget是不可變的凤壁,Element吩屹、RenderObject是可變的,正是這樣大大提高的Flutter的性能拧抖。

可以理解Widget只是配置信息煤搜,實(shí)際重點(diǎn)工作都在Element中進(jìn)行,也就是build階段唧席,而RenderObject負(fù)責(zé)布局及繪制的工作擦盾;打個(gè)比方嘲驾,Widget是戰(zhàn)略部署人員,他只負(fù)責(zé)部署戰(zhàn)略迹卢,當(dāng)一套戰(zhàn)略部署需要修改的時(shí)候辽故,并不會(huì)在原有基礎(chǔ)上修改,而是再次制定新的方案腐碱,制定完成后將該方案交給實(shí)施方案的負(fù)責(zé)人(Element)誊垢,此時(shí)負(fù)責(zé)人將新方案與舊的方案加以比較,修改變動(dòng)點(diǎn)症见,將具體的方案流程交給(RenderObject)去實(shí)現(xiàn)喂走。

再看一下官方的一個(gè)例子:

image.png

首先Recanle green Widget下面有一個(gè)子Widget Circle blue,綠色組件創(chuàng)建一個(gè)Element谋作,再創(chuàng)建一個(gè)RenderObject芋肠,Element同時(shí)持有兩者的引用;接下來(lái)藍(lán)色組件創(chuàng)建一個(gè)Element遵蚜,并將其掛在到父Element上帖池,再創(chuàng)建一個(gè)RenderObject,attach到了父RenderObjuect的插槽谬晕,此時(shí)渲Render tree建立碘裕。

Element負(fù)責(zé)build階段,接下來(lái)看下Element Tree攒钳,Element構(gòu)建了Element Tree帮孔,它的職責(zé)就是維護(hù)這棵樹(shù),可以理解Element Tree是一個(gè)“虛擬DOM”不撑,由于DOM每次更新操作都會(huì)重新渲染整個(gè)DOM文兢,非常耗性能,所以出現(xiàn)了虛擬DOM的概念焕檬,也就是通過(guò)diff算法姆坚,只更新改變的元素就好,大大提升了效率实愚,Element Tree也在flutter中扮演了這樣的角色兼呵,如statefulWidget通過(guò)state.setState通知Element改變,Element對(duì)需要更新的Widget標(biāo)記為dirty狀態(tài)(被標(biāo)記dirty的Element會(huì)加到dirty list中)腊敲,表示這個(gè)Element需要被重建击喂。

RenderObject負(fù)責(zé)渲染,在build后碰辅,開(kāi)始布局及繪制(這里涉及到約束布局的概念懂昂,下面會(huì)說(shuō)一下),之后生成適量描述數(shù)據(jù)没宾,這部分就是RenderObject的工作凌彬。接下來(lái)就是上面提到過(guò)的光柵化及Skia處理后送往GPU沸柔。

布局約束
image.png

Flutter是盒子約束模型,上圖中的每個(gè)節(jié)點(diǎn)都是RenderObject铲敛,父節(jié)點(diǎn)會(huì)將約束傳達(dá)給下面的所有子節(jié)點(diǎn)褐澎,如最大最小寬高;子節(jié)點(diǎn)會(huì)依據(jù)約束定義具體size原探,將具體的size乱凿,如width:200、height:200咽弦,告訴父節(jié)點(diǎn)一直傳給頂部徒蟆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市型型,隨后出現(xiàn)的幾起案子段审,更是在濱河造成了極大的恐慌,老刑警劉巖闹蒜,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寺枉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绷落,警方通過(guò)查閱死者的電腦和手機(jī)姥闪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)砌烁,“玉大人筐喳,你說(shuō)我怎么就攤上這事『恚” “怎么了避归?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)管呵。 經(jīng)常有香客問(wèn)我梳毙,道長(zhǎng),這世上最難降的妖魔是什么捐下? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任账锹,我火速辦了婚禮,結(jié)果婚禮上坷襟,老公的妹妹穿的比我還像新娘奸柬。我一直安慰自己,他們只是感情好啤握,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布鸟缕。 她就那樣靜靜地躺著晶框,像睡著了一般排抬。 火紅的嫁衣襯著肌膚如雪懂从。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天蹲蒲,我揣著相機(jī)與錄音番甩,去河邊找鬼。 笑死届搁,一個(gè)胖子當(dāng)著我的面吹牛缘薛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卡睦,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宴胧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了表锻?” 一聲冷哼從身側(cè)響起恕齐,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞬逊,沒(méi)想到半個(gè)月后显歧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡确镊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年士骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕾域。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拷肌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出束铭,到底是詐尸還是另有隱情廓块,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布契沫,位于F島的核電站带猴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏懈万。R本人自食惡果不足惜拴清,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望会通。 院中可真熱鬧口予,春花似錦、人聲如沸涕侈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至木张,卻和暖如春众辨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舷礼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鹃彻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人妻献。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓蛛株,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親育拨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谨履,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容