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