一、Flutter Widget的生命周期

項(xiàng)目地址:https://github.com/Code-Yeong/FlutterDemo

1、引言

在開發(fā)flutter項(xiàng)目過程中我們肯定離不開組件,無論是布局、動畫還是按鈕、標(biāo)簽,這些在flutter中都由大大小小的組件構(gòu)成。組件從創(chuàng)建、繪制到銷毀的各個(gè)階段都有不同的回調(diào)函數(shù)執(zhí)行相應(yīng)的任務(wù),這些回調(diào)函數(shù)也構(gòu)成了組件的生命周期。下面本文主要圍繞著StatefullWidget的生命周期展開討論,希望對大家有所幫助。

2、StatefulWidget介紹

StatefulWidget是一個(gè)抽象類,使用時(shí)此組件只需要繼承這個(gè)類即可,下面是StatefulWidget的源碼:

abstract class StatefulWidget extends Widget {
  /// Initializes [key] for subclasses.
  const StatefulWidget({ Key key }) : super(key: key);

  @override
  StatefulElement createElement() => StatefulElement(this);

  @protected
  State createState();
}

在使用時(shí),子類需要重寫crateElement()函數(shù)和createState(),這兩個(gè)函數(shù)的主要作用是:前者在element樹中創(chuàng)建一個(gè)新的element,在此函數(shù)中用戶無需做任何修改;后者的作用是創(chuàng)建出一個(gè)state用于存儲組件的狀態(tài),值得注意的是同一個(gè)組件被創(chuàng)建多次,那么創(chuàng)建出的state數(shù)量和組件數(shù)一致,也就是說組件與state一一對應(yīng)。

createState()函數(shù)的返回值是一個(gè)State類型的對象,因此我們需要在這個(gè)函數(shù)中創(chuàng)建并返回一個(gè)State類型的值,首先我們看看State對應(yīng)的源碼(這里刪除了源碼中的注釋和一些無關(guān)的屬性、函數(shù),若有需要請對照官方文檔閱讀):

abstract class State<T extends StatefulWidget> extends Diagnosticable {

  @protected
  @mustCallSuper
  void initState() {
    assert(_debugLifecycleState == _StateLifecycle.created);
  }

  @mustCallSuper
  @protected
  void didUpdateWidget(covariant T oldWidget) { }

  @protected
  @mustCallSuper
  void reassemble() { }

  @protected
  void setState(VoidCallback fn) {
   //.......
    _element.markNeedsBuild();
  }

  @protected
  @mustCallSuper
  void deactivate() { }

  @protected
  @mustCallSuper
  void dispose() {
    assert(_debugLifecycleState == _StateLifecycle.ready);
    assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
  }

  @protected
  Widget build(BuildContext context);

  @protected
  @mustCallSuper
  void didChangeDependencies() { }
}

這里保留了幾個(gè)與組件生命收起相關(guān)的函數(shù),分別是initState()didUpdateWidget()、deactivate()、dispose()build()以及didChangeDependencies(),其作用就不細(xì)說,下面開始探究其生命周期。

3、StatefulWidget組件生命周期

首先我們創(chuàng)建了一個(gè)TELifeCycleOfState類繼承自StatefulWidget,在它的兩個(gè)回調(diào)函數(shù)種分別向控制臺輸出log,代碼如下

class TELifeCycleOfState extends StatefulWidget {
  @override
  State createState() {
    print("parent-->createState");
    return _TELifeCycleOfState();
  }

  @override
  StatefulElement createElement() {
    print("parent-->createElement");
    return StatefulElement(this);
  }
}

然后在創(chuàng)建_TELifeCycleOfState類,繼承自State類并重寫其回調(diào)函數(shù),同樣我們在State的回調(diào)函數(shù)中分別向控制臺打印log。

class _TELifeCycleOfState extends State<TELifeCycleOfState{
  num _count = 0;
  @override
  void initState() {
    super.initState();
    print("parent-->initState");
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("parent-->didChangeDependencies");
  }

  @override
  Widget build(BuildContext context) {
    print("parent-->build");

    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
            icon: Icon(Icons.arrow_back_ios),
            onPressed: () {
              Navigator.of(context).pop();
            }),
        title: Text("Test lifeCycle"),
      ),
      body: Container(
        child: Center(
          child: Text('${_count}'),
        ),
      ),
      floatingActionButton: IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            setState(() {
              _count++;
            });
          }),
    );
  }

  @override
  void dispose() {
    print("parent-->dispose");
    super.dispose();
  }

  @override
  void deactivate() {
    super.deactivate();
    print("parent-->deactivate");
  }

  @override
  void reassemble() {
    super.reassemble();
    print("parent-->reassemble");
  }

  @override
  void didUpdateWidget(TELifeCycleOfState oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("parent-->didUpdateWidget");
  }
}

我們在頁面中添加了一個(gè)floatingActionButton,每次點(diǎn)擊這個(gè)按鈕,計(jì)數(shù)_count的值加1并顯示在頁面上。下面我們運(yùn)行代碼,觀察通過日志輸出詳情分析組件的生命周期函數(shù)執(zhí)行情況。

ios模擬器運(yùn)行截圖

程序運(yùn)行起來之后什么都不干,我們首先再來查看log日志輸出情況:

flutter: parent-->createElement
flutter: parent-->createState
flutter: parent-->initState
flutter: parent-->didChangeDependencies
flutter: parent-->build

然后接著點(diǎn)擊右下角“+”按鈕讓計(jì)數(shù)加1,再觀察日志輸出情況:

flutter: parent-->createElement
flutter: parent-->createState
flutter: parent-->initState
flutter: parent-->didChangeDependencies
flutter: parent-->build
flutter: parent-->build

再接著按“home”件然程序進(jìn)入后臺,我們觀察到日志沒有任何變化,也就是說上述生命周期函數(shù)都沒有被執(zhí)行。
接著我們讓程序再次進(jìn)入前臺執(zhí)行,并推出頁面,日志變化如下:

flutter: parent-->createElement
flutter: parent-->createState
flutter: parent-->initState
flutter: parent-->didChangeDependencies
flutter: parent-->build
flutter: parent-->build
flutter: parent-->deactivate
flutter: parent-->dispose

至此,組件生命周期暫時(shí)已經(jīng)“結(jié)束”,我們總結(jié)一下,上述執(zhí)行過程中,組件生命周期大致是這么個(gè)情況:
createElement -> createState -> initState -> didChangeDependencies -> build -> deactivate -> dispose

對比一下AndroidActivity的生命周期(下圖是從android官網(wǎng)摘取的圖片),我們發(fā)現(xiàn)flutter組件的生命周期缺少了onPause()、onResume()等回調(diào)函數(shù)。

acticuty生命周期(圖片來源于https://developer.android.com/guide/components/activities/activity-lifecycle.html )

Activity相比StatefulWidget“缺少”了幾個(gè)重要的生命周期函數(shù),是不是就意味著組件壓根兒就沒有呢。別擔(dān)心,其實(shí)StatefulWidget也可以有這幾個(gè)生命周期函數(shù),不過這幾個(gè)函數(shù)不再State中,而是在WidgetsBindingObserver中,通過mixin的方式將該組件的接口引入進(jìn)來之后,我們同樣也能實(shí)現(xiàn)向Activity類似的生命周期。下面我們對代碼進(jìn)行相應(yīng)的修改:

class _TELifeCycleOfState extends State<TELifeCycleOfState> with WidgetsBindingObserver {
  num _count = 0;
  @override
  void initState() {
    super.initState();
   //新加內(nèi)容
    WidgetsBinding.instance.addObserver(this);
    print("parent-->initState");
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("parent-->didChangeDependencies");
  }

  @override
  Widget build(BuildContext context) {
    print("parent-->build");

    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
            icon: Icon(Icons.arrow_back_ios),
            onPressed: () {
              Navigator.of(context).pop();
            }),
        title: Text("Test lifeCycle"),
      ),
      body: Container(
        child: Center(
          child: TETextWidget(
            count: _count,
          ),
        ),
      ),
      floatingActionButton: IconButton(
          icon: Icon(Icons.add),
          onPressed: () {
            setState(() {
              _count++;
            });
          }),
    );
  }

  @override
  void dispose() {
    print("parent-->dispose");
    //新加內(nèi)容
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void deactivate() {
    super.deactivate();
    print("parent-->deactivate");
  }

  @override
  void reassemble() {
    super.reassemble();
    print("parent-->reassemble");
  }

  @override
  void didUpdateWidget(TELifeCycleOfState oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("parent-->didUpdateWidget");
  }

   //新加內(nèi)容
  AppLifecycleState _state;

   //新加內(nèi)容
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    _state = state;
    print("state is --> : $_state");
  }
}

然后我們在重復(fù)以上幾個(gè)步驟,得到一下日志輸出:

flutter: parent-->createElement
flutter: parent-->createState
flutter: parent-->initState
flutter: parent-->didChangeDependencies
flutter: parent-->build
flutter: parent-->build
flutter: state is -> AppLifecycleState.inactive
flutter: state is -> AppLifecycleState.paused
flutter: state is -> AppLifecycleState.inactive
flutter: state is -> AppLifecycleState.resumed
flutter: parent-->deactivate
flutter: parent-->dispose

這里的inactive狀態(tài)表示app進(jìn)入了后臺但可見,當(dāng)完全不可見之后才執(zhí)行paused。重新回到可見但不可操作時(shí)又會執(zhí)行一次inactive ,之后再resumed進(jìn)入running狀態(tài)。

我們將上述執(zhí)行直接總結(jié)起來,分析得出以下生命周期圖:


StatefulWidget生命周期

4、結(jié)束語

好啦,就將這么多了。沒有講清楚的地方請諸位多包涵,也歡迎提出修改意見。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容