Flutter入門(十一)生命周期&渲染原理

前言

在做移動(dòng)端開(kāi)發(fā)時(shí),不論是安卓的Activity還是iOS的UIViewController都有自己的生命周期,同理Flutter也有自己的生命周期,今天我們就通過(guò)以下幾個(gè)方面來(lái)探索一下:

  • 1.生命周期的基本概念
  • 2.Widget的生命周期
  • 3.Flutter渲染原理

1.生命周期的基本概念

Flutter生命周期流程

1.1什么是生命周期

  • 1.說(shuō)白了就是回調(diào)函數(shù)
  • 2.讓你知道封裝好的這個(gè)Widget處于什么樣的狀態(tài)

1.2生命周期的作用

  • 1.初始化數(shù)據(jù)
    1.1創(chuàng)建變量、常量
    1.2發(fā)送網(wǎng)絡(luò)請(qǐng)求

  • 2.監(jiān)聽(tīng)小部件的事件

  • 3.管理內(nèi)存
    3.1銷毀數(shù)據(jù)、銷毀監(jiān)聽(tīng)者
    3.2銷毀Timer等等

2.Widget的生命周期

2.1StatelessWidget的生命周期

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
  • 1.構(gòu)造方法
  • 2.build方法

對(duì)于StatelessWidget來(lái)說(shuō),生命周期只有構(gòu)造和build過(guò)程。build是用來(lái)創(chuàng)建Widget的,在每次頁(yè)面刷新時(shí)會(huì)調(diào)用build

2.2StatefulWidget的生命周期

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key? key, required this.title}) : super(key: key) {
    print('Widget構(gòu)造方法來(lái)了');
  }

  @override
  State<MyHomePage> createState() {
    print('Widget的createState方法調(diào)用了');
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState() {
    print('State構(gòu)造方法來(lái)了');
  }

  @override
  void initState() {
    print('State的initState來(lái)了');
    super.initState();
  }

  @override
  void didChangeDependencies() {
    print('State的didChangeDependencies來(lái)了');
    super.didChangeDependencies();
  }

  int _count = 0;

  @override
  Widget build(BuildContext context) {
    print('State的build來(lái)了');
    return Container(
      child: Column(
        children: [
          ElevatedButton(
            onPressed: () {
              _count++;
              setState(() {});
            },
            child: const Icon(Icons.add),
          ),
          Text('$_count'),
        ],
      ),
    );
  }

  @override
  void dispose() {
    print('State的dispose來(lái)了');
    super.dispose();
  }
}
  • 1.Widget構(gòu)造方法
  • 2.WidgetCreateState
  • 3.State構(gòu)造方法
  • 4.StateinitState
  • 5.didChangeDependencies方法(改變依賴關(guān)系);依賴(共享數(shù)據(jù))的InheritedWidget發(fā)生變化之后,didChangeDependencies才會(huì)調(diào)用
  • 6.StateBuild ,當(dāng)調(diào)用setState方法。會(huì)重新調(diào)用Build進(jìn)行渲染,setState方法內(nèi)部主要是利用_element(本質(zhì)是就是context對(duì)象) 調(diào)用 markNeedsBuild
  • 7.當(dāng)Widget銷毀的時(shí)候調(diào)用Statedispose

2.3setState實(shí)現(xiàn)

  @protected
  void setState(VoidCallback fn) {
    assert(fn != null);
    assert(() {
      if (_debugLifecycleState == _StateLifecycle.defunct) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called after dispose(): $this'),
          ErrorDescription(
            'This error happens if you call setState() on a State object for a widget that '
            'no longer appears in the widget tree (e.g., whose parent widget no longer '
            'includes the widget in its build). This error can occur when code calls '
            'setState() from a timer or an animation callback.',
          ),
          ErrorHint(
            'The preferred solution is '
            'to cancel the timer or stop listening to the animation in the dispose() '
            'callback. Another solution is to check the "mounted" property of this '
            'object before calling setState() to ensure the object is still in the '
            'tree.',
          ),
          ErrorHint(
            'This error might indicate a memory leak if setState() is being called '
            'because another object is retaining a reference to this State object '
            'after it has been removed from the tree. To avoid memory leaks, '
            'consider breaking the reference to this object during dispose().',
          ),
        ]);
      }
      if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called in constructor: $this'),
          ErrorHint(
            'This happens when you call setState() on a State object for a widget that '
            "hasn't been inserted into the widget tree yet. It is not necessary to call "
            'setState() in the constructor, since the state is already assumed to be dirty '
            'when it is initially created.',
          ),
        ]);
      }
      return true;
    }());
    final Object? result = fn() as dynamic;
    assert(() {
      if (result is Future) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() callback argument returned a Future.'),
          ErrorDescription(
            'The setState() method on $this was called with a closure or method that '
            'returned a Future. Maybe it is marked as "async".',
          ),
          ErrorHint(
            'Instead of performing asynchronous work inside a call to setState(), first '
            'execute the work (without updating the widget state), and then synchronously '
            'update the state inside a call to setState().',
          ),
        ]);
      }
      // We ignore other types of return values so that you can do things like:
      //   setState(() => x = 3);
      return true;
    }());
    _element!.markNeedsBuild();
  }

setState方法其實(shí)核心就是最后一句_element!.markNeedsBuild();

  BuildContext get context {
    assert(() {
      if (_element == null) {
        throw FlutterError(
          'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
          'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',
        );
      }
      return true;
    }());
    return _element!;
  }
  StatefulElement? _element;

由上面的源碼可以得出_element其實(shí)就是Statebulid方法中的context

3.Flutter渲染原理

實(shí)際上,Flutter的UI繪制包含了三個(gè)元素,Widget,ElementRenderObject。這三個(gè)元素分別組成了三棵樹(shù):Widget 樹(shù),Element 樹(shù)和 RenderObject樹(shù),在Flutter渲染的流程中Flutter引擎渲染是針對(duì)Render樹(shù)中的對(duì)象進(jìn)行渲染

Flutter三棵樹(shù)

系統(tǒng)啟動(dòng)時(shí),runApp方法會(huì)被調(diào)用,Flutter會(huì)從最外層的Widget去遍歷創(chuàng)建一顆Widget樹(shù);

  • 每一個(gè)Widget創(chuàng)建出來(lái)都會(huì)調(diào)用createElement方法創(chuàng)建一個(gè)Element對(duì)象
  • Element加入到Element樹(shù)中,形成Element樹(shù)
  • Element通過(guò)mount方法調(diào)用createRenderObject創(chuàng)建RenderObject對(duì)象,并形成相應(yīng)的RenderObject樹(shù)

StatelessElement 繼承 ComponentElement主要調(diào)用build方法,并且將自己(Element)傳遞出去

StatefulElement 繼承 ComponentElement,調(diào)用creatState方法,創(chuàng)建state,將Widget賦值給State對(duì)象,調(diào)用statebuild方法,并且將自己(Element)傳出去

??注意
只有繼承自RenderObjectWidgetWidget才能創(chuàng)建RenderObject并加入RenderObject樹(shù),被渲染

3.1三棵樹(shù)的作用

  • Widget樹(shù):配置信息,用來(lái)描述UI特征,比如尺寸多大,顏色是什么,位置在哪里
  • Element樹(shù):element是widget的實(shí)際實(shí)例,它同時(shí)持有了widget和renderObject的引用,用來(lái)決定是否進(jìn)行UI更新。
  • RenderObject樹(shù):UI更新的執(zhí)行者,保存了元素的大小,布局等信息。它才是真正調(diào)用渲染引擎去進(jìn)行更新的對(duì)象
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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