古話說:“水之積也不厚,則其負(fù)大舟也無力”奖唯,想要深入框架和語言需要打好基礎(chǔ)门坷,我們了解一下Flutter的核心渲染原則Flutter渲染三棵樹原理
可以用網(wǎng)上看到的博主舉的例子形容得非常恰當(dāng)
Widget(產(chǎn)品經(jīng)理),element(UI),renderObject(程序員),產(chǎn)品經(jīng)理將我們的項(xiàng)目藍(lán)圖構(gòu)建出來,描述給UI,UI將產(chǎn)品經(jīng)理的想法,告訴程序員,程序員根據(jù)設(shè)計(jì)圖開發(fā)程序,這就是簡(jiǎn)單的三棵樹之間的關(guān)系。
一盔沫、原理介紹
Flutter中一切皆是Widget四康,可以通過下面一張圖來熟悉一下具體的三棵樹。
官網(wǎng)介紹Flutter框架的的處理流程
1.根據(jù)Widget樹生成一個(gè)Element樹,Element樹中的節(jié)點(diǎn)都繼承自Element類递览。
2.根據(jù)Element樹生成Render樹(渲染樹)叼屠,渲染樹中的節(jié)點(diǎn)都繼承自RenderObject類。
3.根據(jù)渲染樹生成Layer樹绞铃,然后上屏顯示环鲤,Layer樹中的節(jié)點(diǎn)都繼承自Layer類。
我們可以認(rèn)為Flutter的UI系統(tǒng)包含三棵樹:Widget樹憎兽、Element樹冷离、渲染樹。
依賴關(guān)系為:根據(jù)Widget樹生成Element樹纯命,再依賴于Element樹生成RenderObject 樹
三棵樹的具體介紹:
Widget:只是一個(gè)配置西剥,里面存儲(chǔ)的是有關(guān)視圖渲染的配置信息,包括布局亿汞、渲染屬性瞭空、事件響應(yīng)信息等。是不可變的疗我,主要負(fù)責(zé)描述UI的屬性和布局咆畏,不負(fù)責(zé)實(shí)際的渲染繪制,所以創(chuàng)建成本很低
Element 是分離 WidgetTree 和真正的渲染對(duì)象的中間層吴裤, WidgetTree 用來描述對(duì)應(yīng)的Element 屬性,同時(shí)持有Widget和RenderObject旧找,存放上下文信息,通過它來遍歷視圖樹麦牺,支撐UI結(jié)構(gòu)钮蛛。
RenderObject (渲染樹)用于應(yīng)用界面的布局和繪制,負(fù)責(zé)真正的渲染剖膳,保存了元素的大小魏颓,布局等信息,實(shí)例化一個(gè) RenderObject 是非常耗能的
二吱晒、三棵樹創(chuàng)建順序:
1)Flutter會(huì)構(gòu)建Widget的Widgets樹甸饱;
2)Flutter遍歷Widget樹,然后根據(jù)其中的Widget調(diào)用createElement()來創(chuàng)建相應(yīng)的Element對(duì)象仑濒, 最后將這些對(duì)象組建成Element樹叹话;
3)接下來會(huì)創(chuàng)建第三個(gè)樹,這個(gè)樹中包含了與Widget對(duì)應(yīng)的Element通過createRenderObject()創(chuàng)建 的RenderObject躏精;
三渣刷、三棵樹作用
Widget樹:存放渲染內(nèi)容、視圖布局信息矗烛;
Element樹:存放上下文辅柴,通過 Element 遍歷視圖樹箩溃,Element 同時(shí)持有 Widget 和RenderObject点骑;
RenderObject樹:根據(jù) Widget 的布局屬性進(jìn)行 layout 和繪制黄琼;
Flutter中幾乎所有的對(duì)象都是Widget,而widget又分為StatelessWidget和StatefulWidget疮薇。
StatelessWidget:無中間狀態(tài)的Widget,一旦創(chuàng)建便不可更改,只能再重新創(chuàng)建
StatefulWidget:存在中間狀態(tài),同時(shí)引入了State來存放中間狀態(tài),通過調(diào)用state.setState()進(jìn)行更新
1墓怀、State
通常一個(gè)StatefulWidget會(huì)對(duì)應(yīng)一個(gè)State,State中有兩個(gè)常用的屬性Widget、context
Widget:與state相綁定的Widget實(shí)例 context:StatefulWidget所對(duì)應(yīng)的BuildContext翅阵。
注意:Flutter會(huì)調(diào)用mount方法皆尔,調(diào)用createRanderObject方法双藕。同時(shí)有一個(gè)屬性為mounted變量止状,mounted變量可以判斷當(dāng)前State對(duì)象是否已經(jīng)被插入到樹中烹棉,在進(jìn)行調(diào)用state.setState()進(jìn)行更新的時(shí)候需要確認(rèn)mounted為true的情況。
2怯疤、BuildContext
大家對(duì)于BuildContext肯定見得比較多浆洗,不管StatelessWidget和StatefulWidget里面都有BuildContext。
并且在很多組件中都需要BuildContext集峦,那么BuildContext具體是什么呢伏社,BuildContext是Element的實(shí)例
四、三棵樹聯(lián)系
1塔淤、每一個(gè)Widget都會(huì)創(chuàng)建一個(gè)Element對(duì)象摘昌;
2、隱式調(diào)用createElement方法高蜂,Element加入Element樹中(它會(huì)創(chuàng)建三種Element)聪黎;
3、繼承RenderObjectWidget的Widget會(huì)創(chuàng)建RenderElement妨马;
RenderElement主要是創(chuàng)建RenderObject對(duì)象挺举,分為兩步:創(chuàng)建RanderElement,F(xiàn)lutter會(huì)調(diào)用mount方法烘跺,調(diào)用createRanderObject方法。 4脂崔、StatefulWidget會(huì)創(chuàng)建StatefulElement滤淳,StatefulElement繼承ComponentElement;
createElement 方法中砌左,調(diào)用createState方法脖咐,持有state。將自己(Element)和widget給state持有汇歹。
創(chuàng)建流程:
? ? ? a屁擅、widget調(diào)用createState方法,創(chuàng)建State产弹;
? ? ? b派歌、將Widget賦值給state;
? ? ? c、調(diào)用state的build方法 并且將自己(Element)傳出去胶果。
5匾嘱、StatelessWidget會(huì)創(chuàng)建StatelessElement,StatelessElement繼承ComponentElement早抠;
主要就是調(diào)用build方法 并且將自己(Element)傳出去霎烙。
幾個(gè)知識(shí)點(diǎn):
1、Element樹是一個(gè)管理widget樹和Rander樹的上下文蕊连,build方法中context悬垃,本質(zhì)就是Element。
2甘苍、Flutter的渲染是增量渲染尝蠕,Element是可以被復(fù)用的;
3羊赵、widget不在widget樹中就會(huì)被釋放趟佃,想要不被釋放,一定要持有在widget樹中昧捷;