Flutter State 的生命周期
本文主要介紹類比 Android 和 iOS,了解 Flutter State 的生命周期。
從 Android 或 iOS 轉(zhuǎn)到 Flutter 開發(fā),最讓人疑惑的是 Flutter 如何處理生命周期。
onCreate() 在哪里?viewDidLoad() 呢?我應(yīng)該將業(yè)務(wù)邏輯放在哪里?為什么只有一個(gè) build 方法?
本文將解答這些疑惑。
Android
Activity 生命周期是 Android 開發(fā)必須記住的:
- onCreate
- onStart
- onResume
- onPause
- onStop
- onRestart
- onDestroy
大部分業(yè)務(wù)邏輯放在 onCreate 方法:初始化 view、數(shù)據(jù)庫(kù)、監(jiān)聽器等等。onResume 和 onPause 是判斷用戶離開或進(jìn)入當(dāng)前頁(yè)面的好時(shí)機(jī)。
iOS
UIViewController 的生命周期如下:
- viewDidLoad
- viewWillAppear
- viewDidAppear
- viewWillDisappear
- viewDidDisappear
- viewDidUnload
如你所見,兩個(gè)平臺(tái)均使用幾乎一致的步驟來(lái)創(chuàng)建或銷毀頁(yè)面。大部分業(yè)務(wù)邏輯放在 viewDidLoad(),而 Will/Did Appear/Disappear 用于保存信息,判斷用戶何時(shí)離開頁(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 在樹中。直到 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 樹,在 didChangeDependencies() 立即被調(diào)用。所有的 GUI 渲染發(fā)生在這個(gè)方法,每次 UI 需要重新渲染時(shí)都會(huì)調(diào)用這個(gè)方法。(重新渲染是很廉價(jià)的操作)
didUpdateWidget()
這是一個(gè)不太常見的生命周期方法。一旦 parent widget 有變化需要重繪 UI 時(shí)會(huì)調(diào)用 didUpdateWidget()。這個(gè)方法有一個(gè) oldWidget 參數(shù),可以將它跟當(dāng)前 widget 進(jìn)行比較以執(zhí)行某些額外的業(yè)務(wù)邏輯。
deactivate()
這個(gè)生命周期方法也不太常見。這個(gè)方法被調(diào)用時(shí),意味著 Widget 開始進(jìn)入”死亡”階段。
當(dāng) framework 從樹中移除 State 時(shí)會(huì)調(diào)用本方法。某些情況下,framework 會(huì)重新將 State 對(duì)象加入到樹中。
dispose()
這個(gè)方法也非常重要。當(dāng) Widget 及其 State 從樹中永久移除時(shí)會(huì)調(diào)用這個(gè)方法。此后 Widget 不會(huì)再被構(gòu)建。
你需要在這個(gè)方法中做取消對(duì) stream 的監(jiān)聽、銷毀動(dòng)畫等操作。它是 initState 的反操作。
WidgetsBindingObserver
如果我們想監(jiān)聽?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 方法中開始觀察:
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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flutter 2 源码阅读
- 下一篇: 每个开发人员都应该知道的 15 个 In