在之前的一篇文章 React 生命周期 是我在學(xué)習(xí) React 之初總結(jié)的夸盟,那么現(xiàn)如今正處于學(xué)習(xí) Flutter 之初显歧,遂寫了這篇 Flutter 生命周期。
談起 React 生命周期都會默認(rèn)是 Component 生命周期何鸡,那么 Flutter 中的生命周期是什么呢香罐?
Flutter 一切皆 Widget,因此自然是 Widget 的生命周期铭拧,并是通過 State來體現(xiàn)赃蛛。而 App 則是一個特殊的 Widget,除了需要處理視圖顯示的各個階段(即視圖的生命周期)之外搀菩,還需要應(yīng)對應(yīng)用從啟動到退出所經(jīng)歷的各個狀態(tài)(App 的生命周期)
State 生命周期
如上圖呕臂,State 生命周期可以分為三個階段:創(chuàng)建,更新肪跋,銷毀歧蒋。
創(chuàng)建
依次執(zhí)行: 構(gòu)造方法
-> initState
-> didChangeDependencies
-> build
,隨后完成頁面的渲染
構(gòu)造方法:State 生命周期的起點,F(xiàn)lutter 會通過調(diào)用 StatefulWidget.createState() 來創(chuàng)建一個 State谜洽÷苡常可以通過構(gòu)造方法來接收父 Widget 傳遞的初始化 UI 配置數(shù)據(jù)
initState:在 State 對象被插入視圖樹的時候調(diào)用。在 State 生命周期中只會被調(diào)用一次
didChangeDependencies:用來處理 State 對象依賴關(guān)系變化阐虚,會在 initState() 調(diào)用結(jié)束后被調(diào)用
build:構(gòu)建視圖锌俱。經(jīng)過以上步驟,F(xiàn)ramework 認(rèn)為 State已經(jīng)準(zhǔn)備好了敌呈,于是調(diào)用 build。需要根據(jù)父 Widget 傳遞的初始化數(shù)據(jù)造寝,以及 State 當(dāng)前狀態(tài)磕洪,創(chuàng)建一個 Widget 并返回
更新
setState:當(dāng)狀態(tài)數(shù)據(jù)發(fā)生變化時,調(diào)用該方法告訴 Flutter 數(shù)據(jù)變了
didChangeDependencies:State 對象的依賴關(guān)系發(fā)生變化后诫龙,調(diào)用該方法析显,然后出發(fā)組件構(gòu)建。例如:系統(tǒng)語言或主題變更
didUpdateWidget:當(dāng) Widget 的配置發(fā)生變化签赃。例如:父 Widget 的狀態(tài)發(fā)生變化谷异,熱重載時
一旦??這三個方法被調(diào)用,F(xiàn)lutter 就會銷毀老 Widget锦聊,并調(diào)用 build() 重建 Widget
銷毀
組件銷毀相對簡單歹嘹,比如組件被移除,或是頁面銷毀的時候孔庭,系統(tǒng)會調(diào)用 deactivate() 和 dispose() 這兩個方法
具體調(diào)用機(jī)制:
當(dāng)組件的可見狀態(tài)發(fā)生變化時尺上,deactive 會被調(diào)用,State 會被暫時從視圖樹中移除圆到。頁面切換時怎抛,State 在視圖樹中的位置發(fā)生了變化,需要先暫時移除后再重新添加芽淡,重新觸發(fā)組件重構(gòu)马绝,deactive 也會被調(diào)用
State 被永久從視圖樹中移除時,dispose 會被調(diào)用挣菲。此時富稻,組件就要被銷毀,所以可以進(jìn)行最終的資源釋放己单、移除監(jiān)聽事件唉窃,等等
State生命周期方法對比
方法名 | 功能 | 調(diào)用時機(jī) | 調(diào)用次數(shù) |
---|---|---|---|
構(gòu)造方法 | 接收父 Widget 傳遞的初始UI數(shù)據(jù) | 創(chuàng)建 State 時 | 1 |
initState | 與渲染相關(guān)的初始化工作 | 在State被插入視圖樹時 | 1 |
didChangeDependencies | 處理State對象依賴關(guān)系變化 | initState 后及State對象依賴關(guān)系變化時 | >=1 |
build | 構(gòu)建視圖 | State準(zhǔn)備好數(shù)據(jù)需要渲染時 | >=1 |
setState | 觸發(fā)視圖重建 | 需要刷新UI時 | >=1 |
didUpdateWidget | 處理Widget的配置變化 | 父 Widget setState 觸發(fā)子Widget重建 | >=1 |
deactivate | 組件被移除 | 組件不可見 | >=1 |
dispose | 組件被銷毀 | 組件永久被移除 | 1 |
App 生命周期
App 的生命周期定義的是 App 從移動到退出的全過程
生命周期回調(diào)
didChangeAppLifecycleState
回調(diào)函數(shù)中,有一個參數(shù)類型為 AppLifecycleSate
的枚舉類纹笼,該類封裝了 App 生命周期狀態(tài)纹份。常用狀態(tài):resumed
,inactive
,paused
- resumed:可見的蔓涧,響應(yīng)用戶輸入
- inactive:處在不活動狀態(tài)件已,無法處理用戶響應(yīng)
- paused:不可見并不能響應(yīng)用戶輸入,但在后臺繼續(xù)活動中
App 切換前后臺時狀態(tài)變化:
從后臺切入前臺:
AppLifecycleState.paused
->AppLifecycleState.inactive
->AppLifecycleState.resumed
從前臺切入后臺:
AppLifecycleState.resumed
->AppLifecycleState.inactive
->AppLifecycleState.paused
幀繪制回調(diào)
除了需要監(jiān)聽 App 的生命周期回調(diào)做相應(yīng)處理之外元暴,還需要在組件渲染之后做一些與顯示安全相關(guān)的操作
ios 中可以通過 dispatch_async((dispatch_get_main_queue), ^{...})
讓操作在下一個 RunLoop 執(zhí)行篷扩;Android 可以通過 View.post()
插入消息隊列,來保證在組件渲染后進(jìn)行相關(guān)操作
Flutter 中茉盏,WidgetsBinding
提供了單次 Frame 繪制回調(diào)鉴未,以及實時 Frame 繪制回調(diào)兩種機(jī)制
- 單次 Frame 繪制回調(diào),通過
addPostFrameCallback
實現(xiàn)鸠姨。會在當(dāng)前 Frame 繪制完成后進(jìn)行回調(diào)铜秆,并且只會回調(diào)一次,如果要再次監(jiān)聽需再設(shè)置
WidgetsBinding.instance.addPostFrameCallback((_){
print("單次Frame繪制回調(diào)"); // 只回調(diào)一次
});
- 實時 Frame 繪制回調(diào)讶迁,通過
addPersistentFrameCallback
實現(xiàn)连茧。在每次繪制 Frame 結(jié)束后進(jìn)行回調(diào)
WidgetsBinding.instance.addPersistentFrameCallback((_){
print("實時Frame繪制回調(diào)");//每幀都回調(diào)
});