Flutter中的StatefulWidget及其生命周期

級別: ★☆☆☆☆
標(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)域慷。由StatefulWidgetcreateState創(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)。

state創(chuàng)建時機(jī)

關(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í)行初始化戴尸。
場景:如果Statebuild方法依賴于本身可以改變狀態(tài)的對象時煎饼。(例如ChangeNotifierStream,或者可以訂閱并接收通知的其他對象)正確的方式是:

  1. initState中訂閱此對象校赤。
  2. 當(dāng)elementwidget發(fā)生需要更新的情況:Widget.canUpdate吆玖,在didUpdateWidget中從舊的widgetunsubscribe并且對新的widget執(zhí)行subscribe
  3. disposeunsubscribe马篮。

注意點:此方法中不能使用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)用此方法的幾個不同的場景如下:

  1. 調(diào)用initState后;
  2. 調(diào)用didUpdateWidget后岖圈;
  3. setState調(diào)用后讹语;
  4. State對象的依賴(dependency)改變;比如:之前build時引用的InheritedWidget更改蜂科。
  5. 調(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僅僅只是連接了StateStatefulElement的不可變的實例接奈,因此StatefulWidget的生命周期,依賴于StatefulElement通孽,而State卻是其最簡單直接的體現(xiàn)形式序宦。

為了能更好的理解StatefulWidget的生命周期,我畫了一張關(guān)于State背苦、StatefulElement互捌、ComponentElement的關(guān)系圖行剂。

`State`秕噪、`StatefulElement`、`Component`厚宰、`Element`的關(guān)系圖.png

Flutter中的RenderObjectElement與RenderObjectWidget

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ò)展
淺談編譯過程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腌巾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铲觉,更是在濱河造成了極大的恐慌澈蝙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撵幽,死亡現(xiàn)場離奇詭異灯荧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盐杂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門漏麦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人况褪,你說我怎么就攤上這事撕贞。” “怎么了测垛?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵捏膨,是天一觀的道長。 經(jīng)常有香客問我食侮,道長号涯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任锯七,我火速辦了婚禮链快,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眉尸。我一直安慰自己域蜗,他們只是感情好巨双,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霉祸,像睡著了一般筑累。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上丝蹭,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天慢宗,我揣著相機(jī)與錄音,去河邊找鬼奔穿。 笑死镜沽,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贱田。 我是一名探鬼主播缅茉,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼湘换!你這毒婦竟也來了宾舅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤彩倚,失蹤者是張志新(化名)和其女友劉穎筹我,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帆离,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蔬蕊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哥谷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岸夯。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖们妥,靈堂內(nèi)的尸體忽然破棺而出猜扮,到底是詐尸還是另有隱情,我是刑警寧澤监婶,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布旅赢,位于F島的核電站,受9級特大地震影響惑惶,放射性物質(zhì)發(fā)生泄漏煮盼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一带污、第九天 我趴在偏房一處隱蔽的房頂上張望僵控。 院中可真熱鬧,春花似錦鱼冀、人聲如沸报破。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泛烙。三九已至理卑,卻和暖如春翘紊,著一層夾襖步出監(jiān)牢的瞬間蔽氨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工帆疟, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留鹉究,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓踪宠,卻偏偏與公主長得像自赔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子柳琢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354