简介

Flutter的根底是widget,依据是否须要跟用户进行交互,widget则能够分为StatelessWidget和StatefulWidget。StatelessWidget只能依据传入的状态进行简略的初始化widget,如果要实现跟用户交互这种简单的性能,则须要用到StatefulWidget。

然而对于StatefulWidget自身来说,它并不存储任何状态,所有的状态都是寄存在和StatefulWidget关联的State中的。

明天,让咱们来摸索一下StatefulWidget和State的关系。

StatefuWidget和State

StatefulWidget的定义很简略,它是一个abstract class,继承它只须要实现一个createState的办法:

abstract class StatefulWidget extends Widget {   const StatefulWidget({ Key? key }) : super(key: key);  @override  StatefulElement createElement() => StatefulElement(this);  @protected  @factory  State createState(); }

留神,这里的createState是一个工厂类办法。这就意味着一个StatefulWidget能够创立多个State。

比方,如果从树中删除一个StatefulWidget,稍后再次将其插入到树中,Flutter将再次调用StatefulWidget.createState 来创立一个新的 State对象。

那么State中能够拜访创立它的StatefulWidget吗?答案是必定的。

在State中定义了一个T类型的widget, 这个T是StatefulWidget的子类:

abstract class State<T extends StatefulWidget> with Diagnosticable {  T get widget => _widget!;  T? _widget;

这里的_widget是不须要咱们自行去设置的,这个_widget是由flutter框架在调用initState之前设置的。该_widget实际上就是和State关联的StatefulWidget。

咱们能够间接在在State中应用widget来援用它。

State的生命周期

讲完StatefulWidget和State的关系之后,接下来咱们来理解一下State是如何变动的,艰深的讲,就是State的生命周期是怎么样的。

通常来说,一个State的生命周期有4个状态,别离是created,initialized,ready和defunct状态,这四个状态是定义在枚举类_StateLifecycle中的:

enum _StateLifecycle {  /// State曾经被创立胜利了,State.initState办法被调用。  created,  /// State.initState办法尽管被调用了,然而State对象还没有构建结束。 这时候会调用State.didChangeDependencies办法.  initialized,  /// State对象创立胜利,State.dispose办法还没有被调用。  /// called.  ready,  /// State.dispose办法被调用过了,State对象不容许再调用build办法。  defunct,}

咱们具体来解说一下State的生命周期。

首先,flutter为了创立State对象,会调用StatefulWidget.createState办法。因为StatefulWidget.createState办法只是简略的new一个State对象,所以这个时候State对象就处于created的状态。

这个新创建的State对象会和一个BuildContext相关联.留神这个关联关系是永久性的,不会发生变化的。

尽管关联关系不会发生变化,然而BuildContext自身是能够在树上进行挪动的。这时候的State处于mounted状态。

接下来,flutter会调用State中的 initState办法。

对于State的具体实现来说,须要重写这个initState的办法,依据和State关联的BuildContext和Widget来初始化State的状态。其中BuildContext和Widget能够通过应用State的context和widget属性来拜访获取。

而后flutter框架会调用state的didChangeDependencies办法。

什么时候会去调用这个办法呢?依据flutter的说法,当State依赖的对象发生变化的时候就会调用。

举个例子,如果在State的build办法中援用了一个InheritedWidget对象,而这个InheritedWidget对象起初产生了变动。这个时候flutter就会调用didChangeDependencies办法。

咱们看下State中该办法的定义:

  void didChangeDependencies() { }

能够看到这个办法自身是一个空的办法体,因为并不是形象办法,所以子类并不需要强制实现它。

为什么一般来说State的子对象并不需要重写这个办法呢?这是因为flutter如果检测到依赖有变动的时候,会去调用State的build办法。通常来说,咱们并不需要这么频繁的进行重构。

当然,也会有一些非凡的状况,比方实时网络通讯这种实时性要求很高的状况。

这个时候,State对象齐全初始化结束了,接着就能够有限次数调用build办法,来重构用户界面。

State还能够被动调用setState办法来重构子树。

除了State被动调用setState办法之外,还有一些内部的变动会导致State的变动,比方:

void didUpdateWidget(covariant T oldWidget) { }

这个办法什么时候会被调用呢?

咱们晓得Widget是不会变的,每个Widget都有一个惟一的key用来标记,然而parent Widget能够应用同一个key和runtimeType来对以后的widget进行批改。因为Widget是不变的,所以生成一个新的widget。这时候flutter就会调用State中的didUpdateWidget办法,并且将老的Widget作为参数传入。

留神,flutter框架会在调用didUpdateWidget之后主动调用build办法,所以咱们在写程序的过程中,留神不要反复调用。

如果是在开发过程中,flutter还反对热重载,这时候会调用state的reassemble办法:

void reassemble() { }

flutter框架会在触发热重载之后,调用build办法,所以一般来说,咱们并不需要重写reassemble办法。

刚刚咱们提到了parent Widget可能批改以后Widget的配置文件,如果批改了以后Widget的key,那么老的widget就处于一个deactivate 的状态,widget中的deactivate 办法就会被调用:

  void deactivate() {    super.deactivate();    assert(      !renderObject.attached,      'A RenderObject was still attached when attempting to deactivate its '      'RenderObjectElement: $renderObject',    );  }

咱们能够重写这个办法,来解决一些资源的清理工作。

留神,当初这个widget是deactivate状态,然而并不象征这它就没有用了。因为flutter还能够将这个widget再从新插入对象树中,持续应用。reinsert是通过调用State对象的build办法来实现的。

这个操作只有是在一个animation frame完结之前操作都是能够的。这样做的益处就是,state还能够保留局部资源并不开释,从而晋升效率。

最初,如果State的确是不须要应用了,就会调用State的dispose 办法:

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

当State的dispose办法被调用之后,State就处于unmounted状态。这时候State的setState办法就不能再被调用了,这就示意State的生命周期完结了。

总结

以上就是State和State的生命周期相干的介绍。

更多内容请参考 http://www.flydean.com/03-flutter-state/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」,懂技术,更懂你!