StatelessWidget
初始化
build
通過build()渲染
StatefulWidget
初始化
State初始化時會依次執(zhí)行 : 構(gòu)造函數(shù) > initState > didChangeDependencies > Widget build , 此時頁面加載完成。
構(gòu)造函數(shù)
調(diào)用次數(shù):1次
這個函數(shù)嚴(yán)格意義上來講不屬于生命周期的一部分,因?yàn)檫@個時候State的widget屬性為空,無法在構(gòu)造函數(shù)中訪問widget的屬性 。但是構(gòu)造函數(shù)必然是要第一個調(diào)用的。可以在這一部分接收前一個頁面?zhèn)鬟f過來的數(shù)據(jù)。
intState
調(diào)用次數(shù):1次
當(dāng)插入渲染樹的時候調(diào)用,這個函數(shù)在生命周期中只調(diào)用一次。這里可以做一些初始化工作,比如初始化State的變量。
在這個方法中,上下文context可用,但你還不能真正使用它,因?yàn)榭蚣苓€沒有完全將狀態(tài)與它相關(guān)聯(lián)
initState()方法完成后,State對象現(xiàn)在已初始化,上下文可用。
didChangeDependencies
- 初始化時,在initState()之后立刻調(diào)用
- 當(dāng)依賴的InheritedWidget rebuild,會觸發(fā)此接口被調(diào)用
這個函數(shù)會緊跟在initState之后調(diào)用,并且可以調(diào)用BuildContext.inheritFromWidgetOfExactType, 也就說在didChangeDependencies中,可以跨組件拿到數(shù)據(jù)
在此階段,由于上下文context可用,您可以使用它。
運(yùn)行時
build
調(diào)用次數(shù):多次
初始化之后開始繪制界面,當(dāng)setState觸發(fā)的時候會再次被調(diào)用
didUpdateWidget
這個函數(shù)一般用于比較新、老Widget,看看哪些屬性改變了,并對State做一些調(diào)整。
需要注意的是,涉及到controller的變更,需要在這個函數(shù)中移除老的controller的監(jiān)聽,并創(chuàng)建新controller的監(jiān)聽。
組件移除
組件移除,例如頁面銷毀的時候會依次執(zhí)行:deactivate > dispose
deactivate
在dispose之前,會調(diào)用這個函數(shù)。實(shí)測在組件課件狀態(tài)變化的時候會調(diào)用,當(dāng)組件卸載時也會先一步dispose調(diào)用。
dispose
調(diào)用次數(shù):1次
hot reload
reassemble
一旦到這個階段,組件就要被銷毀了,這個函數(shù)一般會移除監(jiān)聽,清理環(huán)境。
State
State鏈接到一個BuildContext,BuildContext鏈接到Widget的一個實(shí)例
widget
Widget State類訪問其任何變量
print(widget.title);
currentState
父Widget可以通過以下方式訪問其子級的狀態(tài)
SnackBar是Scaffold的子Widget
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: new Text(widget.title == null ? 'ADD' : 'EDIT'),
),
body: new Container(
padding: EdgeInsets.all(20.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Container(
margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
child: new RaisedButton(
color: Colors.purple,
textColor: Color(0xFFFFFFFF),
onPressed: () {
_scaffoldKey.currentState.showSnackBar(
SnackBar(content: Text('Not supported.'))
);
},
child: new Text('保存'),
),
)
],
),
)
);
還有一種也可以實(shí)現(xiàn)類似currentState的功能
floatingActionButton: ScaffoldButton(
onPressedButton: () {
_incrementCounter();
},
));
class ScaffoldButton extends StatelessWidget {
ScaffoldButton({this.onPressedButton});
final VoidCallback onPressedButton;
@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () {
print(
'FloatingActionButton onPressed context hashcode = ${context.hashCode}');
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('I am context from Scaffold')));
onPressedButton();
},
tooltip: 'Increment',
child: new Icon(Icons.add),
);
}
}
祖先Widget
final MyExposingWidget widget = context.ancestorWidgetOfExactType(MyExposingWidget);
final MyExposingWidgetState state = widget?.myState;
InheritedWidget
InheritedWidget是一個特殊的Widget,您可以將其作為另一個子樹的父級放在Widgets樹中。該子樹的所有小部件都必須能夠與該InheritedWidget公開的數(shù)據(jù)進(jìn)行交互。