setState()如何重建子窗口小部件?

时间:2019-04-09 12:27:39

标签: dart flutter widget

我只需要了解在调用setState()时,抖动的有状态小部件如何构建其有状态的子级。请查看下面的代码。

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  Widget build(BuildContext context) {
    print("Parent build method invoked");
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            StatefulChild(), // Keeping this line gives the output 1
            statefulChild, // Keeping this line gives the output 2
            RaisedButton(
              child: Text('Click me'),
              onPressed: () {
                setState(() {});
              },
            )
          ],
        ),
      ),
    );
  }

  StatefulChild statefulChild = StatefulChild();
}

class StatefulChild extends StatefulWidget {
  StatefulChildState createState() => StatefulChildState();
}

class StatefulChildState extends State<StatefulChild> {
  @override
  Widget build(BuildContext context) {
    print("Child00 build method invoked");
    return Container();
  }
}

按下RaisedButton时,

输出1 //仅保留StatefulChild()

I/flutter ( 2903): Parent build method invoked
I/flutter ( 2903): Child00 build method invoked

输出2 //仅保留statefulChild

I/flutter ( 2903): Parent build method invoked

这里有什么区别?引擎盖下会发生什么?非常感谢详细的解释。

2 个答案:

答案 0 :(得分:1)

重建窗口小部件树时,Flutter使用==比较build方法返回的先前和新窗口小部件。

在这种情况下有两种情况:

  • ==false。在这种情况下,Flutter将比较runtimeTypekey以确定是否应保留前一个小部件的状态。然后Flutter在该小部件上调用build

  • ==true。在这种情况下,Flutter会中止构建小部件树(也不会调用build)。

由于小部件的不变性,这是一种优化的可能。

由于小部件是不可变的,因此如果==没有更改,则意味着没有任何要更新的内容。因此Flutter可以安全地对其进行优化。

答案 1 :(得分:0)

使用setState(())时只会调用build()。现在,在此方法中,您再次调用StatefulChild()(第一行),它进一步实例化了该类,因此该类的build()方法得以执行。

但是当您使用statefulChild时,它并没有创建新实例,因为

StatefulChild statefulChild = StatefulChild();

build()方法之外使用。所以它只被调用过一次。