关于flutter:flutter系列之用来管理复杂状态的State详解

111次阅读

共计 3704 个字符,预计需要花费 10 分钟才能阅读完成。

简介

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/

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

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

正文完
 0