flutter Widget的生命周期

做过Android/iOS开发的都知道我们的页面都是由生命周期,我们在不同生命周期的回调方法里会做一些处理。对于flutter而言 一切皆是Widget,所以了解Widget的生命周期也是必不可少的!
那我们先从简单的StateLessWidget开始吧。
下图是官网对StateLessWidget 生命周期的描述,不难看出StateLessWidget只有两个过程,初始化和build。


StateLessWidget构建

StateLessWidget 源码如下:

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

  /// Creates a [StatelessElement] to manage this widget's location in the tree.
  ///
  /// It is uncommon for subclasses to override this method.
  @override
  StatelessElement createElement() => StatelessElement(this);

  /// Describes the part of the user interface represented by this widget.
  @protected
  Widget build(BuildContext context);
}

StatelessWidget的定义也是很简单,就三个方法。构造方法很好理解,build方法其实就是我们自己实现如何构建布局我们的页面的。createElement我们基本在开发中不会用到,那它做了些什么呢?以下是StatelessElement的源码:

class StatelessElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);

  @override
  StatelessWidget get widget => super.widget as StatelessWidget;

  @override
  Widget build() => widget.build(this);

  @override
  void update(StatelessWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    _dirty = true;
    rebuild();
  }
}

在StatelessElement 我们可以到build方法里调用了widget 的build方法,并且将当前element传到了widget的build方法里,也就对应着我们经常看到的build(BuildContext context),其实BuildContext 就是element。upate方法感觉应该是更新的时候调用的。那么到底是在哪调的呢,什么时候调的呢?我们继续跟进下ComponentElement的源码:

class ComponentElement extends Element{

@override
void performRebuild() {
………
Widget build;

build = build();

………
_child = updateChild(_child, build, slot);
…………
}
}

由于代码篇幅较大,摘出重点。可以看到performRebuild这个方法里调用了build方法,StatelessElement里的build方法又调用到了widget里的build方法。到这 StateLessWidget的声明周期已经完事了。相信你一定有不少疑问,比如 那什么时候显示,什么时候销毁,ComponentElement的performRebuild方法又是什么时候调用的呢?这里先只做Widget内方法调用顺序的分析,以上问题会在启动流程部分给出解答,别着急哈。

StatefulWidget的生命周期

image.png

我们知道StatefulWidget是有状态的Widget,Widget创建出来之后是不可变,但是状态是可以变的,管理这个状态的就是State,我们可以通过调用期setState方法去刷新Widget。先看个我们平时写StatefulWidget的例子:

class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);

@override
_MyStatefulWidget createState() =>  _MyStatefulWidget();
}


class _MyStatefulWidget extends State {

@override
Widget build(BuildContext context){

……………
}

}

我们在State里重写了build方法,记住这一点哟。跟StateLessWidget一样我们来看看StatefulWidget的源码:

class StatefulWidget extends Widget{


const StatefulWidget({Key key}) : super(key: key);

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


@proteced
State createState();

}

比StateLessWidget多了个createState方法,同样我们跟进StatefulElement,来探索下createState 是啥时候调用的。

class StatefulElement extends ComponentElement{

StatefulElement(StatefulWidget widget)
: _state = widget.createState(),
super(widget){

……………
}

……………

@override
void _firstBuild() {
………
final dynamic debugCheckForReturnedFuture = _state.initState();
………

_state.didChangeDependencies();

………

super._firstBuild()
}
……………


}

可以看到createState 在StatefulWidget构造的时候就创建了,同时发现_firstBuild 好像是第一次创建的意思,我们来看看 这里做了啥,果然在这里调用了initState 方法,之后是didChangeDependencies,那build方法是啥时候调用的呢?我们看看super._firstBuild()做了什么。

class ComponentElement extends Element{

void _firstBuild() {
rebuild();
}

void rebuild(){
.................
performRebuild();
.......
}

@override
void performRebuild() {
………
Widget build;

build = build();

………
_child = updateChild(_child, build, slot);
…………
}
}

其实这个super._firstBuild()会触发rebuild()函数,rebuild()函数又会触发performRebuild(),在performRebuild()函数里我们看到调用了build()函数,至此StatefulWidget的创建过程基本完事。我们可以看到在performRebuild里调用了updateChild,

 Element updateChild(Element child, Widget newWidget, dynamic newSlot) {
    if (newWidget == null) {
      if (child != null)
        deactivateChild(child);//// widget不活跃
      return null;
    }
    Element newChild;
    if (child != null) {
      bool hasSameSuperclass = true;
      assert(() {
        final int oldElementClass = Element._debugConcreteSubtype(child);
        final int newWidgetClass = Widget._debugConcreteSubtype(newWidget);
        hasSameSuperclass = oldElementClass == newWidgetClass;
        return true;
      }());
      if (hasSameSuperclass && child.widget == newWidget) {
       ..........
      } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
       ..........
        }());
        newChild = child;
      } else {
        deactivateChild(child);  //// widget不活跃
        assert(child._parent == null);
        newChild = inflateWidget(newWidget, newSlot);
      }
    } else {
    .......
    }

  .............

    return newChild;
  }

在这里会看到deactivateChild,这个方法是将当前element标注为不活跃,暂时不会显示在屏幕上。此时会调用State的deactivate,不能在该方法内做销毁资源操作,因为该element有可能会再次被置为活跃状态。当我们执行了pop,framework会触发unmount()函数,state dispose会被调用,我们可以在这个方法里做资源销毁。

image.png

总结下StatefulWidget生命周期:

  • initState 适合做初始化工作
  • build 避免在build内做些逻辑代码,因为在调用setState是build方法会重新触发,容易产生问题
  • dispose 释放资源。
image.png

到这里我们就StateLessWidget,StatefulWidget的声明周期分析完了。本次的分析是基于widget和state内方法调用顺序为思路分析的,对于element内的方法调用顺序会在接下来的 flutter app启动流程里分析。
欢迎拍砖,交流!

你可能感兴趣的:(flutter Widget的生命周期)