setState() 如何重建子部件?

Ire*_*aka 10 widget dart flutter

我只需要了解在调用 setState() 时 flutter stateful widgets 如何构建它们的 stateful child。请看下面的代码。

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

当按下 RaisedButton 时,

输出 1 // 只保留StatefulChild(),

I/flutter ( 2903): Parent build method invoked
I/flutter ( 2903): Child00 build method invoked
Run Code Online (Sandbox Code Playgroud)

输出 2 // 只保留statefulChild,

I/flutter ( 2903): Parent build method invoked
Run Code Online (Sandbox Code Playgroud)

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

Rém*_*let 8

当小部件树重建时,Flutter 使用==build方法返回的前一个和新小部件进行比较。

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

  • ==false。在这种情况下,Flutter 将比较runtimeType&key以了解是否应保留前一个小部件的状态。然后 Flutter 调用build那个小部件

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

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

由于小部件是不可变的,如果==没有改变,则意味着没有什么可更新的。因此,Flutter 可以安全地优化它。


Cop*_*oad 0

当您setState(())仅使用时build(),将被调用。现在,在这个方法中,您再次调用StatefulChild()(第一行),它进一步实例化此类,以便build()执行此类的方法。

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

StatefulChild statefulChild = StatefulChild();
Run Code Online (Sandbox Code Playgroud)

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