欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Flutter学习(四)实例解析State的生命周期

程序员文章站 2022-06-01 17:07:40
...

周期图

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");
  }

}

把上面的三段函数拼接在一起,第一次运行,
Flutter学习(四)实例解析State的生命周期
可以看到首先打印的是

I/flutter (15097): initState
I/flutter (15097): didChangeDependencies
I/flutter (15097): Build
I/flutter (15097): reassemble
I/flutter (15097): didUpdateWidget

每次点击模拟器中的按钮,都会打印一次Build,也就是说,执行一次Build()函数
如果点击⚡️热重载的话,将会发现
Flutter学习(四)实例解析State的生命周期
打印的变成了

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

小结

也就是说,
initStatedidChangeDependencies只会被调用一次,不管多少次⚡️热重载都只有第一次会出现
所以
initState一般做一些一次性的工作,比如初始化订阅子树的事件通知等
didChangeDependencies是在State对象发生依赖变化时被调用,就和上面一样,第一次构建的时候调用,重新热重载的时候不再调用,

除了以上两个,每次点击按钮都出现的build()就很常见了,在下面情况下都会被调用

  1. 在调用 initState() 之后。
  2. 在调用 didUpdateWidget() 之后。
  3. 在调用 setState() 之后。
  4. 在调用 didChangeDependencies() 之后。
  5. 在 State 对象从树中一个位置移除后(会调用 deactivate)又重新插入到树的其它位置之后。

reassemble():是为了开发调试而提供的,只要热重载就会调用,在Release模式中就不会调用
didUpdateWidget是在Widget发生rebuild的时候调用。
deactivate():当 State 对象从树中被移除时,会调用此回调。在一些场景下,Flutter framework 会将 State 对象重新插到树中,如包含此 State 对象的子树在树的一个位置移动到另一个位置时(可以通过 GlobalKey 来实现)。如果移除后没有重新插入到树中则紧接着会调用 dispose() 方法。
dispose():当 State 对象从树中被永久移除时调用;通常在此回调中释放资源。

以上就是关于flutter中State的生命周期部分,参考自《flutter实战》