Flutter学习(四)实例解析State的生命周期
周期图
实例演绎
现在我们来看一个实例,首先定义一个MyApp,然后他的body将返回CounterWidget,也就是我们要研究的对象
import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Button"),
),
body: CounterWidget(),
),
);
}
}
下面是关于计数的核心代码,由于我继承的是StatefulWidget
,所以在CounterWidget
中显示有构造函数,并设置初始值initValue
为0,然后再创建一个_CounterWidget
,本质上是一个State
,继承自CounterWidget
,所以他也有initValue
,在initState()函数中通过widget.initValue赋初值给到_counter
,这个_counter
就是在模拟器中显示的数字。
模拟器中会出现一个FlatButton按钮,上面的数字是_counter
的值,每次点击这个按钮,_counter
就加1。
class CounterWidget extends StatefulWidget{
const CounterWidget({
Key key,
this.initValue:0
});
final int initValue;
@override
_CounterWidget createState() {
return new _CounterWidget();
}
}
class _CounterWidget extends State<CounterWidget>{
int _counter;
@override
void initState(){
super.initState();
_counter=widget.initValue;//widget是哪里来的?
@override
Widget build(BuildContext context) {
print("Build"); //每次点击按钮都会打印Build
return Scaffold(
body:Center(
child:FlatButton(
child:Text('$_counter'),
onPressed: ()=>setState(()=>_counter++),
),
)
);
}
你可能会奇怪这个widget.initValue是哪来的,因为_CounterWidget所继承的State是一个抽象类,自带了widget实例,那为什么写作State呢?
因为State的写法如下
abstract class State<T extends StatefulWidget> extends Diagnosticable {
T get widget => _widget;
T _widget;
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
可以看到,initState
也在这个类中。
这个widget在这里,就代表了CounterWidget
,他自然就有initValue
属性。
接下来是一些重写的函数,内容都一样,和上面的build函数是并列关系,有关他们的解释在后文会提
@override
void didUpdateWidget(CounterWidget oldWidget) {
super.didUpdateWidget(oldWidget);
print("didUpdateWidget");
}
@override
void deactivate() {
super.deactivate();
print("deactive");
}
@override
void dispose() {
super.dispose();
print("dispose");
}
@override
void reassemble() {
super.reassemble();
print("reassemble");
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("didChangeDependencies");
}
}
把上面的三段函数拼接在一起,第一次运行,
可以看到首先打印的是
I/flutter (15097): initState
I/flutter (15097): didChangeDependencies
I/flutter (15097): Build
I/flutter (15097): reassemble
I/flutter (15097): didUpdateWidget
每次点击模拟器中的按钮,都会打印一次Build,也就是说,执行一次Build()
函数
如果点击⚡️热重载的话,将会发现
打印的变成了
I/flutter (15097): reassemble
I/flutter (15097): didUpdateWidget
I/flutter (15097): Build
可以看到initState()
和didChangeDependencies()
并没有被调用,如果我们把开头提到的MyApp 的body替换为
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Button"),
),
body: Text('新文本'),
),
);
}
再次点击⚡️热重载按钮,就会发现打印出
I/flutter (15097): reassemble
I/flutter (15097): deactive
I/flutter (15097): dispose
如果我们将代码改回来,也就是
body: CounterWidget(),
再次热重载,发现initState与didChangeDependencies再次执行了
I/flutter (15097): initState
I/flutter (15097): didChangeDependencies
I/flutter (15097): Build
小结
也就是说,initState
和didChangeDependencies
只会被调用一次,不管多少次⚡️热重载都只有第一次会出现
所以initState
一般做一些一次性的工作,比如初始化订阅子树的事件通知等didChangeDependencies
是在State对象发生依赖变化时被调用,就和上面一样,第一次构建的时候调用,重新热重载的时候不再调用,
除了以上两个,每次点击按钮都出现的build()
就很常见了,在下面情况下都会被调用
- 在调用
initState()
之后。 - 在调用
didUpdateWidget()
之后。 - 在调用
setState()
之后。 - 在调用
didChangeDependencies()
之后。 - 在 State 对象从树中一个位置移除后(会调用 deactivate)又重新插入到树的其它位置之后。
reassemble()
:是为了开发调试而提供的,只要热重载就会调用,在Release模式中就不会调用
didUpdateWidget是在Widget发生rebuild的时候调用。deactivate()
:当 State 对象从树中被移除时,会调用此回调。在一些场景下,Flutter framework 会将 State 对象重新插到树中,如包含此 State 对象的子树在树的一个位置移动到另一个位置时(可以通过 GlobalKey 来实现)。如果移除后没有重新插入到树中则紧接着会调用 dispose() 方法。dispose()
:当 State 对象从树中被永久移除时调用;通常在此回调中释放资源。
以上就是关于flutter中State的生命周期部分,参考自《flutter实战》
上一篇: JS中放大镜