- State 的生命周期和 StatefulWidget 不同餐禁,當(dāng) StatefulWidget 狀態(tài)改變后就會(huì)被重建,但是 State 不會(huì)改變突照,但是當(dāng) StatefulWidget 在 View 樹(shù)中移除再插入又會(huì)生成新的 State帮非。參考下文 State.context.
- initState -> build -> 狀態(tài)改變 -> didUpdateWidget -> build --->移除.
在學(xué)習(xí) flutter 的時(shí)候,總會(huì)用到 StatefulWidget,它是一個(gè)有狀態(tài)的 widget末盔,會(huì)根據(jù)不同狀態(tài)有不同顯示筑舅,它的生命周期與 State 有關(guān),它的基本寫(xiě)法如下
// flutter官方教程里面的一個(gè)類陨舱,點(diǎn)擊一個(gè)關(guān)注的星星翠拣,然后就表明已經(jīng)關(guān)注。再點(diǎn)擊表示不再關(guān)注游盲,默認(rèn)狀態(tài)是已關(guān)注误墓,關(guān)注數(shù)是41
class FavoriteWidget extends StatefulWidget {
@override
_FavoriteWidgetState createState() => new _FavoriteWidgetState();
}
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 41;
void _toggleFavorite() {
setState(() {
// If the lake is currently favorited, unfavorite it. Otherwise, favorite it.
_favoriteCount = _isFavorited?_favoriteCount -1:_favoriteCount +1 ;
_isFavorited = !_isFavorited;
});
}
@override
Widget build(BuildContext context) {
return new Widget(
// build by states
);
}
}
將 FavoriteWidget 插入到 Views 樹(shù)中的時(shí)候,每當(dāng)調(diào)用 States.setState() 時(shí)益缎,都會(huì)重新build一次FavoriteWidget 谜慌,然后將新的 Views代替原先的,并顯示給用戶莺奔。
您可能想知道為什么 StatefulWidget 和 State 是單獨(dú)的對(duì)象欣范。在 Flutter 中,這兩種類型的對(duì)象具有不同的生命周期: Widget 是臨時(shí)對(duì)象令哟,用于構(gòu)建當(dāng)前狀態(tài)下的應(yīng)用程序恼琼,而 State 對(duì)象在多次調(diào)用build()之間保持不變,允許它們記住信息(狀態(tài))励饵。
State的生命周期
總體介紹一下生命周期驳癌,大致可以看成三個(gè)階段:
- 初始化(插入渲染樹(shù))
- 狀態(tài)改變(在渲染樹(shù)中存在)
- 銷毀(從渲染樹(shù)種移除)
先舉 FavoriteWidget 為例,當(dāng)這個(gè) Widget 首次插入到樹(shù)中時(shí)役听,框架會(huì)調(diào)用其 createState 函數(shù)以創(chuàng)建一個(gè)新的_FavoriteWidgetState實(shí)例來(lái)與該樹(shù)中的相應(yīng)位置關(guān)聯(lián)(請(qǐng)注意颓鲜,我們通常命名State子類時(shí)帶一個(gè)下劃線,這表示其是私有的)典予。 當(dāng)這個(gè)widget的父級(jí)重建時(shí)甜滨,父級(jí)將創(chuàng)建一個(gè)新的FavoriteWidget實(shí)例,但是Flutter框架將重用已經(jīng)在樹(shù)中的_FavoriteWidgetState實(shí)例瘤袖,而不是再次調(diào)用createState創(chuàng)建一個(gè)新的衣摩。
從 StatefulWidget調(diào)用createState之后,框架將新的狀態(tài)對(duì)象插入樹(shù)中捂敌,然后調(diào)用 State 的initState艾扮,接著如上圖所示走了一遍自身的生命周期。需要注意的是占婉,StatefulWidget 和 State 是不同的生命周期。
生命周期詳解
initState
當(dāng)插入渲染樹(shù)的時(shí)候調(diào)用逆济,這個(gè)函數(shù)在生命周期中只調(diào)用一次磺箕。這里可以做一些初始化工作抛虫,比如初始化State的變量松靡。
didChangeDependencies
這個(gè)函數(shù)會(huì)緊跟在initState之后調(diào)用,并且可以調(diào)用BuildContext.inheritFromWidgetOfExactType建椰,那么BuildContext.inheritFromWidgetOfExactType的使用場(chǎng)景是什么呢?
static TabController of(BuildContext context) {
final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
return scope?.controller;
}
實(shí)際上就是調(diào)用BuildContext.inheritFromWidgetOfExactType阅茶,也就說(shuō)在didChangeDependencies中,可以跨組件拿到數(shù)據(jù)谅海。
didUpdateWidget
當(dāng)組件的狀態(tài)改變的時(shí)候就會(huì)調(diào)用didUpdateWidget,比如調(diào)用了setState.
實(shí)際上這里flutter框架會(huì)創(chuàng)建一個(gè)新的Widget,綁定本State脸哀,并在這個(gè)函數(shù)中傳遞老的Widget。
這個(gè)函數(shù)一般用于比較新扭吁、老Widget,看看哪些屬性改變了侥袜,并對(duì)State做一些調(diào)整。
需要注意的是浦旱,涉及到controller的變更九杂,需要在這個(gè)函數(shù)中移除老的controller的監(jiān)聽(tīng),并創(chuàng)建新controller的監(jiān)聽(tīng)例隆。
image
image
deactivate
在dispose之前镀层,會(huì)調(diào)用這個(gè)函數(shù)。
dispose
一旦到這個(gè)階段唱逢,組件就要被銷毀了,這個(gè)函數(shù)一般會(huì)移除監(jiān)聽(tīng)备韧,清理環(huán)境《⒑‘
總結(jié)
階段 | 調(diào)用次數(shù) |
---|---|
構(gòu)造函數(shù) | 1 |
initState | 1 |
didChangeDependencies | >=1 |
didUpdateWidget | >=1 |
deactivate | >=1 |
dispose | 1 |
各個(gè)方法的解釋:
- initState:插入渲染樹(shù)時(shí)調(diào)用捧挺,只調(diào)用一次闽烙,widget創(chuàng)建執(zhí)行的第一個(gè)方法,可以再里面初始化一些數(shù)據(jù),以及綁定控制器
- didChangeDependencies:當(dāng)State對(duì)象的依賴發(fā)生變化時(shí)會(huì)被調(diào)用疏旨;例如:在之前build() 中包含了一個(gè)InheritedWidget,然后在之后的build() 中InheritedWidget發(fā)生了變化遏匆,那么此時(shí)InheritedWidget的子widget的didChangeDependencies()回調(diào)都會(huì)被調(diào)用谁榜。InheritedWidget這個(gè)widget可以由父控件向子控件共享數(shù)據(jù),案例可以參考 scoped_model開(kāi)源庫(kù)帝蒿。
- build :它主要是用于構(gòu)建Widget子樹(shù)的巷怜,調(diào)用次數(shù):多次,初始化之后開(kāi)始繪制界面延塑,當(dāng)setState觸發(fā)的時(shí)候會(huì)再次被調(diào)用
- didUpdateWidget:組件狀態(tài)改變時(shí)候調(diào)用,可能會(huì)調(diào)用多次
- deactivate:當(dāng) State 被暫時(shí)從視圖樹(shù)中移除時(shí)胖替,會(huì)調(diào)用這個(gè)函數(shù)豫缨。
頁(yè)面切換時(shí),也會(huì)調(diào)用它好芭,因?yàn)榇藭r(shí) State 在視圖樹(shù)中的位置發(fā)生了變化,需要先暫時(shí)移除后添加招狸。 - dispose():當(dāng)State對(duì)象從樹(shù)中被永久移除時(shí)調(diào)用;通常在此回調(diào)中釋放資源裙戏。
- reassemble:此回調(diào)是專門(mén)為了開(kāi)發(fā)調(diào)試而提供的,在熱重載(hot reload)時(shí)會(huì)被調(diào)用营勤,此回調(diào)在Release模式下永遠(yuǎn)不會(huì)被調(diào)用壹罚。