生命周期
Flutter生命周期說白了就是回調(diào)方法(函數(shù))功偿,主要是監(jiān)聽Widget事件,內(nèi)存管理(銷毀).
- 每一個
widget
都對應(yīng)一個(或多個)Element
。Widget只是用于描述Element的一個配置文件念搬,實際在Framework層管理頁面的構(gòu)建,渲染等摆出,都是通過
Element完成朗徊,Element由Widget創(chuàng)建,并且持有
Widget對象偎漫,每一個Widget都會對應(yīng)一個(或多個)Element爷恳。 - Element: 同時持有Widget和RenderObject,存放上下文信息象踊,通過它來遍歷視圖樹温亲,支撐UI結(jié)構(gòu)。
- 調(diào)用
setState()
相當(dāng)于調(diào)用了markNeedsBuild
杯矩,即_element.markNeedsBuild(); - setState()過程其實只是將當(dāng)前對應(yīng)的Element標(biāo)記為
臟dirty
栈虚,并且添加到_dirtyElements合中 - 重新渲染過程是一個增量改變码邻,注意這里的
增量改變是指Element樹和渲染render樹
致讥,而不是指widget樹
宫患,原有的不變的Element拿來復(fù)用
。widget肯定都是要重新創(chuàng)建阵子,只是在渲染的時候在element樹中再決定是重新渲染還是復(fù)用
种呐。渲染時不是加載的widget樹形入,而是Render樹羔砾,決定是否重用是在element的canUpdate
。 - 為什么設(shè)計成三棵樹呢相艇?個人認為因為中間的Element樹也對應(yīng)contenxt颖杏,意思是
上下文
的意思,也就是說Element樹持有Widget樹和Render樹的關(guān)系坛芽,這樣處理效率更高留储。
widget與element與render
widget初始化時內(nèi)部會隱式
調(diào)用createElement
;
StatelessWidget內(nèi)部會調(diào)用
createElement
咙轩,同時將widget
實例當(dāng)參數(shù)傳遞進去获讳,并返回(stateful/less)Element
,而他們都繼承自Element的子類ComponentElement
,接著調(diào)用ComponentElement
里的mount
方法的_firstBuild
,最終走到performReBuild
活喊,這一步會拿出_widget
并調(diào)用build
方法丐膝,并把Element
當(dāng)做參數(shù)傳遞,所以最終會調(diào)用到widget的build的方法钾菊,由此也可以證明BuildContext
就是element
帅矗,且Element有個屬性_widget
用來指向外部widget變量。StateFulWidget會比上面流程多兩部煞烫,在
Element創(chuàng)建后
立馬調(diào)用widget.createState
浑此,并把_state保存在Element。接著給state.widget賦值widget滞详,這也是為什么能在state方法里只能調(diào)用widget的原因凛俱。Row、Cloumn
這類Widget里createElement返回的是Element的子類RenderObjectElement
料饥,接著調(diào)用mount
方法里的createRenderObject
蒲犬。
并不是所有的widget都會
獨立
渲染,只有繼承自RenderObjectWidget的才會創(chuàng)建renderObject對象岸啡。Flutter引擎是針對Render樹進行渲染原叮。
直接在頁面節(jié)點調(diào)用setState()將會重新調(diào)用所有Widget(包括他們中的各種嵌套)的build()方法,如果我們的需求是一個較為復(fù)雜的頁面凰狞,這樣帶來的開銷消耗可想而知篇裁。當(dāng)我們在一個高節(jié)點調(diào)用setState()的時候會構(gòu)建再次build所有的Widget,雖然不一定掛載到Element樹中赡若,但是平時我們使用的Widget中往往嵌套多個其他類型的Widget,每個build()方法走下來最終也會帶來不小的開銷团甲,因此通過各種狀態(tài)管理方案逾冬,
Stream
等方式,只做局部刷新
,是我們?nèi)粘i_發(fā)中應(yīng)該養(yǎng)成的良好習(xí)慣身腻。
Key
Element的canUpdate
比較的是runtimeType
和Key
产还,運用了diff算法
,所以為了更加精確的區(qū)分oldwidget和newwidget嘀趟,需要在widget的初始化方法里傳入Key
:super(key:key);
GlobalKey:可以獲取到對應(yīng)的Widget的State對象脐区,用來更新局部控件。_globalKey.currentState.setState();
她按。
優(yōu)先級隊列
then
優(yōu)先級最高牛隅,微任務(wù)scheduleMicrotask
次之,Future
最次酌泰。
混合開發(fā)
Flutter和原生來回切換會消耗性能
和內(nèi)存泄漏
媒佣。
Flutter和原生通信需要用到MethodChannel
.