【Flutter學習】之 Flutter 的生命周期


一,概述

Flutter 的生命周期分為兩個部分:

  • Widget 的生命周期
  • App 的生命周期

二,Widget 的生命周期

Flutter 里的 Widget 分為 StatelessWidget 和 StatefulWidget 兩種,這兩種 Widget 的生命周期是不一樣的,我們接下來具體來看。

  • StatelessWidget 的生命周期

    StatelessWidget 的生命周期只有一個,就是:

    • build

      build 是用來創建 Widget 的,但因為 build 在每次界面刷新的時候都會調用,所以不要在 build 里寫業務邏輯,可以把業務邏輯寫到你的 StatelessWidget 的構造函數里。

      StatelessWidget 的 build 函數代碼如下:

      class TestWidget extends StatelessWidget{
        @override
        Widget build(BuildContext context) {
          // TODO: implement build
          print('StatelessWidget build');
          return Text('Test');
        }
      }
  • StatefulWidget 的生命周期

    • StatefulWidget 的生命周期比較復雜,依次為:

      • createState
      • initState
      • didChangeDependencies
      • build
      • addPostFrameCallback
      • didUpdateWidget
      • deactivate
      • dispose

    • 生命周期圖


    • 接下來具體介紹一下各個生命周期。
      • createState

        createState 是 StatefulWidget 里創建 State 的方法,當要創建新的 StatefulWidget 的時候,會立即執行 createState,而且只執行一次,createState 必須要實現:

        class MyScreen extends StatefulWidget {
          @override
          _MyScreenState createState() => _MyScreenState();
        }
      • initState

        前面的 createState 是在創建 StatefulWidget 的時候會調用,initState 是 StatefulWidget 創建完后調用的第一個方法,而且只執行一次,類似於 Android 的 onCreate、iOS 的 viewDidLoad(),所以在這里 View 並沒有渲染,但是這時 StatefulWidget 已經被加載到渲染樹里了,這時 StatefulWidget 的 mount的值會變為 true,直到 dispose調用的時候才會變為 false。可以在 initState里做一些初始化的操作。

        在 override initState的時候必須要調用 super.initState():

        @override
        void initState() {
          super.initState();
          ...
        }
      • didChangeDependencies

        當 StatefulWidget 第一次創建的時候,didChangeDependencies方法會在 initState方法之后立即調用,之后當 StatefulWidget 刷新的時候,就不會調用了,除非你的 StatefulWidget 依賴的 InheritedWidget 發生變化之后,didChangeDependencies才會調用,所以 didChangeDependencies有可能會被調用多次。

        這個函數會緊跟在initState之后調用,並且可以調用BuildContext.inheritFromWidgetOfExactType,那么BuildContext.inheritFromWidgetOfExactType的使用場景是什么呢?最經典的應用場景是

        new DefaultTabController(length: 3, child: new TabBar(
        tabs: [ "主頁","訂單","我的" ]
        .map( (data)=>new Text(data) ).toList(),

        TabBar本來需要定義一個TabController,但是在外面套一層DefaultTabController就不需要定義TabContrller了,看下源碼:

        @override
        void didChangeDependencies() {
          super.didChangeDependencies();
           _updateTabController();
           _initIndicatorPainter();
        }
        
        void _updateTabController() {
          final TabController newController = widget.controller ?? DefaultTabController.of(context);
          ...
        }

        注意到這里DefaultTabController.of(context)

        static TabController of(BuildContext context) {
          final _TabControllerScope scope = context.inheritFromWidgetOfExactType(_TabControllerScope);
          return scope?.controller;
        }

        實際上就是調用BuildContext.inheritFromWidgetOfExactType,也就說在didChangeDependencies中,可以跨組件拿到數據。

      • build

        在 StatefulWidget 第一次創建的時候,build方法會在 didChangeDependencies方法之后立即調用,另外一種會調用 build方法的場景是,每當 UI 需要重新渲染的時候(setState觸發),build都會被調用,所以 build會被多次調用,然后 返回要渲染的 Widget。千萬不要在 build里做除了創建 Widget 之外的操作,因為這個會影響 UI 的渲染效率。

      • addPostFrameCallback

        addPostFrameCallback是 StatefulWidge 渲染結束的回調,只會被調用一次,之后 StatefulWidget 需要刷新 UI 也不會被調用,addPostFrameCallback的使用方法是在 initState里添加回調:

        import 'package:flutter/scheduler.dart';
        @override
        void initState() {
          super.initState();
          SchedulerBinding.instance.addPostFrameCallback((_) => {});
        }
      • didUpdateWidget

        祖先節點rebuild widget時調用 .當組件的狀態改變的時候就會調用didUpdateWidget.(可能會調用多次)

        理論上setState的時候會調用,但我實際操作的時候發現只是做setState的操作的時候沒有調用這個方法。而在我改變代碼hot reload時候會調用 didUpdateWidget 並執行 build…

        實際上這里flutter框架會創建一個新的Widget,綁定本State,並在這個函數中傳遞老的Widget。這個函數一般用於比較新、老Widget,看看哪些屬性改變了,並對State做一些調整。

        需要注意的是,涉及到controller的變更,需要在這個函數中移除老的controller的監聽,並創建新controller的監聽。

      • deactivate(組件移除時)

        當要將 State 對象從渲染樹中移除的時候,就會調用 deactivate生命周期,這標志着 StatefulWidget 將要銷毀,但是有時候 State 不會被銷毀,而是重新插入到渲染樹種。

      • dispose(組件移除時)

        當 View 不需要再顯示,從渲染樹中移除的時候,State 就會永久的從渲染樹中移除,就會調用 dispose生命周期,這時候就可以在 dispose里做一些取消監聽、動畫的操作,和 initState是相反的。

三,App 的生命周期

AppLifecycleState 就是 App 的生命周期,有:

  • resumed
  • inactive
  • paused
  • suspending

如果想要知道 Flutter App 的生命周期,例如 Flutter 是在前台還是在后台,就需要使用到 WidgetsBindingObserver了,使用方法如下:

  1. State 的類 mix WidgetsBindingObserver:

    class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
        ...
    }
  2. 在 State 的 initState里添加監聽:

    @override
      void initState(){
        super.initState();
        WidgetsBinding.instance.addObserver(this);
      }
  3. 在 State 的 dispose里移除監聽:

     @override
      void dispose() {
        // TODO: implement dispose
        super.dispose();
        WidgetsBinding.instance.removeObserver(this);
      }
  4. 在 State 里 override didChangeAppLifecycleState

    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
      super.didChangeAppLifecycleState(state);
      if (state == AppLifecycleState.paused) {
        // went to Background
      }
      if (state == AppLifecycleState.resumed) {
        // came back to Foreground
      }
    }

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM