Flutter State 的生命周期
本文主要介紹類比 Android 和 iOS,了解 Flutter State 的生命周期。
從 Android 或 iOS 轉(zhuǎn)到 Flutter 開(kāi)發(fā),最讓人疑惑的是 Flutter 如何處理生命周期。
onCreate() 在哪里?viewDidLoad() 呢?我應(yīng)該將業(yè)務(wù)邏輯放在哪里?為什么只有一個(gè) build 方法?
本文將解答這些疑惑。
Android
Activity 生命周期是 Android 開(kāi)發(fā)必須記住的:
- onCreate
- onStart
- onResume
- onPause
- onStop
- onRestart
- onDestroy
大部分業(yè)務(wù)邏輯放在 onCreate 方法:初始化 view、數(shù)據(jù)庫(kù)、監(jiān)聽(tīng)器等等。onResume 和 onPause 是判斷用戶離開(kāi)或進(jìn)入當(dāng)前頁(yè)面的好時(shí)機(jī)。
iOS
UIViewController 的生命周期如下:
- viewDidLoad
- viewWillAppear
- viewDidAppear
- viewWillDisappear
- viewDidDisappear
- viewDidUnload
如你所見(jiàn),兩個(gè)平臺(tái)均使用幾乎一致的步驟來(lái)創(chuàng)建或銷毀頁(yè)面。大部分業(yè)務(wù)邏輯放在 viewDidLoad(),而 Will/Did Appear/Disappear 用于保存信息,判斷用戶何時(shí)離開(kāi)頁(yè)面等等。
Flutter
在 Flutter 中呢?Widget 也遵循類似規(guī)則嗎?
Flutter 中主要有兩種 Widget:StatelessWidget 和 StatefulWidget。本文重點(diǎn)放在 StatefulWidget,因?yàn)樗悬c(diǎn)像 Android 和 iOS 中的某些概念。
StatefulWidget
StatefulWidget 是最重要的 Widget,因?yàn)樗钟?State,它知道何時(shí)發(fā)生變化并進(jìn)行必要的重繪。它的生命周期如下:
- createState
- initState
- didChangeDependencies
- build
- (didUpdateWidget)
— — — — — — — — — — —
- deactivate
- dispose
你可能會(huì)注意到創(chuàng)建階段的 state 比銷毀階段的多,這是因?yàn)閯?chuàng)建/重建 Widget 及其 State 更復(fù)雜。
createState():
構(gòu)建新的 StatefulWidget 時(shí)將調(diào)用 createState(),StatefulWidget 的子類必須覆蓋這個(gè)方法:
class MyScreen extends StatefulWidget {@override_MyScreenState createState() => _MyScreenState(); }initState()
通常需要重寫這個(gè)方法。它是 Widget 創(chuàng)建后調(diào)用的第一個(gè)方法,可以理解成 onCreate() 或 viewDidLoad() 的等價(jià)物。在這個(gè)方法中可以檢查 Widget 某些相關(guān)屬性:是否有被渲染?當(dāng)前是否處理 mounted 狀態(tài)?
mounted
每個(gè) Widget 都有這個(gè)屬性。當(dāng)為 Widget.buildContext 賦值后 mounted 的值變成 true,Widget 在樹(shù)中。直到 dispose 方法被調(diào)用前,mounted 一直為 true。
addPostFrameCallback
可以在 initState 方法中按如下方式調(diào)用 addPostFrameCallback:
import 'package:flutter/scheduler.dart'; @override void initState() {super.initState();SchedulerBinding.instance.addPostFrameCallback((_) => {}); }這個(gè)方法為一幀結(jié)束時(shí)添加回調(diào),回調(diào)方法只會(huì)調(diào)用一次,通知 Widget 構(gòu)建已完成。
didChangeDependencies
widget 構(gòu)建時(shí)第一次調(diào)用 initState() 后立即會(huì)調(diào)用 didChangeDependencies()。如果 StatefulWidgets 依賴某個(gè) InheritedWidget,后者發(fā)生變化時(shí)會(huì)導(dǎo)致 didChangeDependencies() 再次被調(diào)用。
build()
可以肯定地說(shuō)這是最重要的方法。這個(gè)方法依賴整個(gè)待渲染的 Widget 樹(shù),在 didChangeDependencies() 立即被調(diào)用。所有的 GUI 渲染發(fā)生在這個(gè)方法,每次 UI 需要重新渲染時(shí)都會(huì)調(diào)用這個(gè)方法。(重新渲染是很廉價(jià)的操作)
didUpdateWidget()
這是一個(gè)不太常見(jiàn)的生命周期方法。一旦 parent widget 有變化需要重繪 UI 時(shí)會(huì)調(diào)用 didUpdateWidget()。這個(gè)方法有一個(gè) oldWidget 參數(shù),可以將它跟當(dāng)前 widget 進(jìn)行比較以執(zhí)行某些額外的業(yè)務(wù)邏輯。
deactivate()
這個(gè)生命周期方法也不太常見(jiàn)。這個(gè)方法被調(diào)用時(shí),意味著 Widget 開(kāi)始進(jìn)入”死亡”階段。
當(dāng) framework 從樹(shù)中移除 State 時(shí)會(huì)調(diào)用本方法。某些情況下,framework 會(huì)重新將 State 對(duì)象加入到樹(shù)中。
dispose()
這個(gè)方法也非常重要。當(dāng) Widget 及其 State 從樹(shù)中永久移除時(shí)會(huì)調(diào)用這個(gè)方法。此后 Widget 不會(huì)再被構(gòu)建。
你需要在這個(gè)方法中做取消對(duì) stream 的監(jiān)聽(tīng)、銷毀動(dòng)畫(huà)等操作。它是 initState 的反操作。
WidgetsBindingObserver
如果我們想監(jiān)聽(tīng)?wèi)?yīng)用何時(shí)進(jìn)入后臺(tái)該怎么辦?
可以這樣做。對(duì) StatefulWidget 做些小改動(dòng):
class _MyScreenState extends State<MyScreen> with WidgetsBindingObserver我們讓 _MyScreenState 實(shí)現(xiàn)了抽象類 WidgetsBindingObserver,之后就可以觀察應(yīng)用的生命周期狀態(tài)。在 initState 方法中開(kāi)始觀察:
WidgetsBinding.instance.addObserver(this);在 dispose 方法中停止觀察:
WidgetsBinding.instance.removeObserver(this);接下來(lái)在 didChangeAppLifecycleState 接收生命周期的變化即可:
@override void didChangeAppLifecycleState(AppLifecycleState state) {super.didChangeAppLifecycleState(state);if (state == AppLifecycleState.paused) {// went to Background}if (state == AppLifecycleState.resumed) {// came back to Foreground} }這個(gè)技巧很有用。如果你想在應(yīng)用進(jìn)入后臺(tái)時(shí)彈出 notification,或者保存數(shù)據(jù),又或者在用戶點(diǎn) back 回退時(shí)彈出 popup,都可以使用這個(gè)技巧。
總結(jié)
以上是生活随笔為你收集整理的Flutter State 的生命周期的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Flutter 2 源码阅读
- 下一篇: 信息系统项目管理师之风险管理