简介
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/
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」,懂技术,更懂你!