級別: ★☆☆☆☆
標(biāo)簽:「Flutter」「StatefulWidget 」「生命周期 」
作者: 沐靈洛
審校: QiShare團(tuán)隊
StatefulWidget
是什么矗晃?
狀態(tài)可變的widget
稻据。
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key key }) : super(key: key);
@override
StatefulElement createElement() => StatefulElement(this);
@protected
State createState();
}
通過其類的定義能夠看到StatefulWidget
配置StatefulElement
酬屉。
關(guān)于State
StatefulWidget
的內(nèi)部邏輯與狀態(tài)域慷。由StatefulWidget
的createState
創(chuàng)建。
StatefulWidget
實例本身是不可變的, 在StatefulWidget
中它可變的狀態(tài)存儲在與之關(guān)聯(lián)的State
對象中,不管什么時候溉奕,只要在樹中mount
一個新的StatefulElement
(必然需要注入一個StatefulWidget
)或注入一個StatefulWidget
時,framework
都會調(diào)用一次createState
方法忍啤。(其實呀加勤,在StatefulElement
構(gòu)造的時候,就會調(diào)用createState
,創(chuàng)建_state
對象)鳄梅。
這意味著如果StatefulWidget
被插入到樹中的多個位置叠国,則會有多個State
對象分別與它們關(guān)聯(lián)。
關(guān)于此類的定義如下:
abstract class State<T extends StatefulWidget> with Diagnosticable {
T get widget => _widget;
T _widget;
...
BuildContext get context => _element;
StatefulElement _element;
bool get mounted => _element != null;
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
@protected
@mustCallSuper
void reassemble() { }
@protected
void setState(VoidCallback fn) {
....
final dynamic result = fn() as dynamic;
....
_element.markNeedsBuild();
}
@protected
@mustCallSuper
void deactivate() { }
@protected
@mustCallSuper
void dispose() {
}
@protected
Widget build(BuildContext context);
@protected
@mustCallSuper
void didChangeDependencies() { }
...
}
方法概述
initState
描述: 重寫此方法以執(zhí)行初始化戴尸。
場景:如果State
的build
方法依賴于本身可以改變狀態(tài)的對象時煎饼。(例如ChangeNotifier
或Stream
,或者可以訂閱并接收通知的其他對象)正確的方式是:
- 在
initState
中訂閱此對象校赤。 - 當(dāng)
element
的widget
發(fā)生需要更新的情況:Widget.canUpdate
吆玖,在didUpdateWidget
中從舊的widget
中unsubscribe
并且對新的widget
執(zhí)行subscribe
。 - 在
dispose
中unsubscribe
马篮。
注意點:此方法中不能使用BuildContext.dependOnInheritedWidgetOfExactType
沾乘。但是此方法被調(diào)用后會立即調(diào)用didChangeDependencies
,在didChangeDependencies
可以使用BuildContext.dependOnInheritedWidgetOfExactType
浑测。
調(diào)用時機(jī):StatefulElement
翅阵,首次插入樹中時會調(diào)用此方法,在build
方法調(diào)用之前調(diào)用迁央。
build
描述: StatefulElement
通過此方法返回的widget
并通過調(diào)用updateChild
來更新自己掷匠。
調(diào)用時機(jī): framework
調(diào)用此方法的幾個不同的場景如下:
- 調(diào)用
initState
后; - 調(diào)用
didUpdateWidget
后岖圈; -
setState
調(diào)用后讹语; -
State
對象的依賴(dependency
)改變;比如:之前build
時引用的InheritedWidget
更改蜂科。 - 調(diào)用了
deactivate
后顽决,然后將State
對象重新插入樹中的另一個位置。
didUpdateWidget
描述: StatefulElement
存在导匣,并且符合Widget.canUpdate
的情況下對StatefulWidget
進(jìn)行更新才菠。
調(diào)用時機(jī): 不論何時只要StatefulElement
的配置widget
改變的時候就會調(diào)用。
注意:didUpdateWidget
方法最終會調(diào)用build
方法贡定,因此在此方法中調(diào)用setState
是多余的赋访。如果重寫此方法,請確保調(diào)用super.didUpdateWidget(oldWidget)
缓待。
didChangeDependencies
調(diào)用時機(jī): 當(dāng)此State
對象的依賴項(InheritedWidget
)更改時調(diào)用蚓耽。
reassemble
描述: 用于開發(fā)階段hot reload
。
調(diào)用時機(jī):hot reload
時調(diào)用命斧,調(diào)用后build
方法也將被調(diào)用田晚。無需在此方法中做任何操作。
deactivate
調(diào)用時機(jī): 當(dāng)StatefulElement
從樹中移除的時候會調(diào)用国葬。
dispose
調(diào)用時機(jī):當(dāng)StatefulElement
從樹中unmount
的時候會調(diào)用。
總結(jié)
StatefulWidget
用以配置StatefulElement
,但在這兩者之間的State
承接了StatefulElement
的生命周期汇四,而StatefulWidget
僅僅只是連接了State
與StatefulElement
的不可變的實例接奈,因此StatefulWidget
的生命周期,依賴于StatefulElement
通孽,而State
卻是其最簡單直接的體現(xiàn)形式序宦。
為了能更好的理解StatefulWidget
的生命周期,我畫了一張關(guān)于State
背苦、StatefulElement
互捌、Component
、Element
的關(guān)系圖行剂。
Flutter中的StatelessWidget及其生命周期
Flutter中的Widget
Flutter中的Element(下篇)
Flutter中的Element(上篇)
iOS 解決 [NSURL fileURLWithPath:] 對 # 的編碼問題
Xcode 調(diào)整導(dǎo)航目錄字體大小b
Swift 5.1 (21) - 泛型
Swift 5.1 (20) - 協(xié)議
Swift 5.1 (19) - 擴(kuò)展
淺談編譯過程