Flutter widget生命周期詳解


前言

和其他的視圖框架比如android的Activity一樣,flutter中的視圖Widget也存在生命周期,生命周期的回調函數提現在了State上面。理解flutter的生命周期,對我們寫出一個合理的控件至關重要。組件State的生命周期整理如下圖所示:


 
Widget 生命周期

大致可以看成三個階段

  • 初始化(插入渲染樹)
  • 狀態改變(在渲染樹中存在)
  • 銷毀(從渲染樹種移除)

構造函數

這個函數不屬於生命周期,因為這個時候State的widget屬性為空,如果要在構造函數中訪問widget的屬性是行不通的。但是構造函數必然是要第一個調用的。

initState

/// Called when this object is inserted into the tree.
當插入渲染樹的時候調用,這個函數在生命周期中只調用一次。這里可以做一些初始化工作,比如初始化State的變量。

didChangeDependencies

/// Called when a dependency of this [State] object changes.

 

 
didChangeDependencies

這個函數會緊跟在initState之后調用,並且可以調用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用場景是什么呢?最經典的應用場景是

 

new DefaultTabController(length: 3, child: new TabBar( tabs: [ "主頁","訂單","我的" ] .map( (data)=>new Text(data) ).toList(), 

TabBar本來需要定義一個TabController,但是在外面套一層DefaultTabController就不需要定義TabContrller了,看下源碼:

@override void didChangeDependencies() { super.didChangeDependencies(); _updateTabController(); _initIndicatorPainter(); } void _updateTabController() { final TabController newController = widget.controller ?? DefaultTabController.of(context); 

注意到這里DefaultTabController.of(context)

 static TabController of(BuildContext context) { final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope); return scope?.controller; } 

實際上就是調用BuildContext.inheritFromWidgetOfExactType,也就說在didChangeDependencies中,可以跨組件拿到數據。

didUpdateWidget

/// Called whenever the widget configuration changes.

 

 
didUpdateWidget

當組件的狀態改變的時候就會調用didUpdateWidget,比如調用了setState.
實際上這里flutter框架會創建一個新的Widget,綁定本State,並在這個函數中傳遞老的Widget。
這個函數一般用於比較新、老Widget,看看哪些屬性改變了,並對State做一些調整。
需要注意的是,涉及到controller的變更,需要在這個函數中移除老的controller的監聽,並創建新controller的監聽。
 
TabBar_didUpdateWidget

 
_updateTabController

 

deactivate

/// Called when this object is removed from the tree.

在dispose之前,會調用這個函數。

dispose

/// Called when this object is removed from the tree permanently.

一旦到這個階段,組件就要被銷毀了,這個函數一般會移除監聽,清理環境。
還是TabBar:


 
dispose

實際場景

假設我們從A頁面跳轉到B頁面, 那么A,B頁面的生命周期會是怎樣的呢?

B頁面進入初始化狀態,依次執行4個函數:構造函數 > initState > didChangeDependencies > Widget build , 此時頁面加載完成,進入運行態。
此時A頁面依次執行deactivate > build函數。注意 此時A頁面並未卸載。

然后我們假設B頁面只有一個按鈕,點擊B頁面中的按鈕,改變按鈕的文字,會執行widget的build方法 ,(理論上也應該執行didUpdateWidget,但我這里沒有)。

這時,我們點擊返回鍵從B頁面返回到A頁面。
A頁面重新顯示,B頁面開始卸載。
那么A先執行deactivate > build , 然后B頁面依次執行:deactivate > dispose 。
此時A頁面進入運行態,B頁面移除。

總結一下

階段 調用次數 是否支持setState
構造函數 1
initState 1 無效(使用setState和不使用一樣)
didChangeDependencies >=1 無效
didUpdateWidget >=1
deactivate >=1
dispose 1


作者:ershixiong
鏈接:https://www.jianshu.com/p/762bb2b7fa00
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM