Flutter核心技術與實戰 11 | 生命週期

XingJimmy發表於2019-11-04

State 生命週期

Flutter核心技術與實戰 11 | 生命週期
State 的生命週期可以分為 3 個階段:建立(插入檢視樹)、更新(在檢視樹中存在)、銷燬(從檢視樹中移除)。

建立

State 初始化時會依次執行 :構造方法 -> initState -> didChangeDependencies -> build,隨後完成頁面渲染。

  • 構造方法是 State 生命週期的起點,Flutter 會通過呼叫 StatefulWidget.createState() 來建立一個 State。我們可以通過構造方法,來接收父 Widget 傳遞的初始化 UI 配置資料。這些配置資料,決定了 Widget 最初的呈現效果。
  • initState,會在 State 物件被插入檢視樹的時候呼叫。這個函式在 State 的生命週期中只會被呼叫一次,所以我們可以在這裡做一些初始化工作,比如為狀態變數設定預設值。
  • didChangeDependencies 則用來專門處理 State 物件依賴關係變化,會在 initState() 呼叫結束後,被 Flutter 呼叫。
  • build,作用是構建檢視。經過以上步驟,Framework 認為 State 已經準備好了,於是呼叫 build。我們需要在這個函式中,根據父 Widget 傳遞過來的初始化配置資料,以及 State 的當前狀態,建立一個 Widget 然後返回。

更新

Widget 的狀態更新,主要由 3 個方法觸發:setState、didchangeDependencies 與 didUpdateWidget。

  • setState:我們最熟悉的方法之一。當狀態資料發生變化時,我們總是通過呼叫這個方法告訴 Flutter:“我這兒的資料變啦,請使用更新後的資料重建 UI!”
  • didChangeDependencies:State 物件的依賴關係發生變化後,Flutter 會回撥這個方法,隨後觸發元件構建。哪些情況下 State 物件的依賴關係會發生變化呢?典型的場景是,系統語言 Locale 或應用主題改變時,系統會通知 State 執行 didChangeDependencies 回撥方法。
  • didUpdateWidget:當 Widget 的配置發生變化時,比如,父 Widget 觸發重建(即父 Widget 的狀態發生變化時),熱過載時,系統會呼叫這個函式。

一旦這三個方法被呼叫,Flutter 隨後就會銷燬老 Widget,並呼叫 build 方法重建 Widget。

銷燬

比如元件被移除,或是頁面銷燬的時候,系統會呼叫 deactivate 和 dispose 這兩個方法,來移除或銷燬元件。

  • 當元件的可見狀態發生變化時,deactivate 函式會被呼叫,這時 State 會被暫時從檢視樹中移除。值得注意的是,頁面切換時,由於 State 物件在檢視樹中的位置發生了變化,需要先暫時移除後再重新新增,重新觸發元件構建,因此這個函式也會被呼叫。
  • 當 State 被永久地從檢視樹中移除時,Flutter 會呼叫 dispose 函式。而一旦到這個階段,元件就要被銷燬了,所以我們可以在這裡進行最終的資源釋放、移除監聽、清理環境,等等。

Flutter核心技術與實戰 11 | 生命週期

App 生命週期

在原生開發中,我們可以通過重寫 Activity、ViewController 生命週期回撥方法,或是註冊應用程式的相關通知,來監聽 App 的生命週期並做相應的處理。而在 Flutter 中,我們可以利用 WidgetsBindingObserver 類,來實現同樣的需求。

abstract class WidgetsBindingObserver {
  //頁面pop
  Future<bool> didPopRoute() => Future<bool>.value(false);
  //頁面push
  Future<bool> didPushRoute(String route) => Future<bool>.value(false);
  //系統視窗相關改變回撥,如旋轉
  void didChangeMetrics() { }
  //文字縮放係數變化
  void didChangeTextScaleFactor() { }
  //系統亮度變化
  void didChangePlatformBrightness() { }
  //本地化語言變化
  void didChangeLocales(List<Locale> locale) { }
  //App生命週期變化
  void didChangeAppLifecycleState(AppLifecycleState state) { }
  //記憶體警告回撥
  void didHaveMemoryPressure() { }
  //Accessibility相關特性回撥
  void didChangeAccessibilityFeatures() {}
}
複製程式碼

生命週期回撥

  • resumed:可見的,並能響應使用者的輸入。
  • inactive:處在不活動狀態,無法處理使用者響應。
  • paused:不可見並不能響應使用者的輸入,但是在後臺繼續活動中。
    Flutter核心技術與實戰 11 | 生命週期

幀繪製回撥

在元件渲染之後做一些與顯示安全相關的操作。

在 iOS 開發中,我們可以通過 dispatch_async(dispatch_get_main_queue(),^{…}) 方法,讓操作在下一個 RunLoop 執行;

在 Android 開發中,我們可以通過 View.post() 插入訊息佇列,來保證在元件渲染後進行相關操作。

  • 單次 Frame 繪製回撥,通過 addPostFrameCallback 實現。它會在當前 Frame 繪製完成後進行進行回撥,並且只會回撥一次,如果要再次監聽則需要再設定一次。
WidgetsBinding.instance.addPostFrameCallback((_){
    print("單次Frame繪製回撥");//只回撥一次
});
複製程式碼
  • 實時 Frame 繪製回撥,則通過 addPersistentFrameCallback 實現。這個函式會在每次繪製 Frame 結束後進行回撥,可以用做 FPS 監測。
WidgetsBinding.instance.addPersistentFrameCallback((_){
  print("實時Frame繪製回撥");//每幀都回撥
});
複製程式碼

總結

State的變化,則會觸發build,重建Widget。比如Widget A開啟新的Widget B,Widget A的State發生變化。

相關文章