我只需要了解一下当调用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
这有什么区别?引擎盖下会发生什么?非常感谢详细的解释。
当窗口小部件树重建时,Flutter使用==
比较build
方法返回的上一个窗口小部件和新窗口小部件。
在这种情况下有两种情况:
==
是false
。在这种情况下,Flutter将比较runtimeType
和key
以了解是否应该保留先前小部件的状态。然后Flutter在那个小部件上调用build
==
是true
。在这种情况下,Flutter中止小部件树的构建(也就是不会调用build
)。由于小部件的不变性,这是一种可能的优化。
由于小部件是不可变的,如果==
没有改变那么它意味着没有什么可以更新。因此,颤动可以安全地优化它。
当你使用setState(())
时,只会调用build()
。现在在这个方法中你再次调用StatefulChild()
(第一行)进一步实例化这个类,这样就可以执行这个类的build()
方法。
但是当你使用statefulChild
时,它并没有创建一个新实例,因为
StatefulChild statefulChild = StatefulChild();
在build()
方法之外使用。所以它只被召唤一次。