setState() 如何重建子部件?
Posted
技术标签:
【中文标题】setState() 如何重建子部件?【英文标题】:How does setState() rebuild child widgets? 【发布时间】:2019-08-30 18:01:15 【问题描述】:我只需要一些关于在调用 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
这里有什么区别?引擎盖下会发生什么?非常感谢详细的解释。
【问题讨论】:
【参考方案1】:当您使用setState(())
时,只会调用build()
。现在在这个方法中,你再次调用StatefulChild()
(第一行),它进一步实例化了这个类,所以这个类的build()
方法被执行。
但是当你使用statefulChild
时,它并没有创建一个新实例,因为
StatefulChild statefulChild = StatefulChild();
在build()
方法之外使用。所以它只被调用了一次。
【讨论】:
我认为实例结构保存在内存中,重建时只调用 build 方法。这些类是否在重建发生时实例化? 这些类实例肯定会保存在内存中,并且在您的新StatefulWidget
方法中,您将在didUpdateWidget()
方法而不是initState()
中收到调用,然后调用build()
方法。 【参考方案2】:
当小部件树重建时,Flutter 使用 ==
比较 build
方法返回的前一个小部件和新小部件。
这种情况有两种情况:
==
是false
。在这种情况下,Flutter 会比较 runtimeType
和 key
以了解是否应该保留前一个小部件的状态。然后 Flutter 在该小部件上调用 build
==
是 true
。在这种情况下,Flutter 会中止构建小部件树(也不会调用 build
)。
由于小部件的不变性,这是一种可能的优化。
由于小部件是不可变的,如果==
没有更改,则意味着没有什么可更新的。因此,Flutter 可以安全地优化它。
【讨论】:
"比较使用 == build 方法返回的先前和新的小部件",U 意思是 build 方法已经被调用。然后在“== 为假”条件下再次说“颤振调用建立在该小部件上”。你到底在说哪个小部件,你能指出父小部件和子小部件吗?请用一个小例子详细说明。以上是关于setState() 如何重建子部件?的主要内容,如果未能解决你的问题,请参考以下文章
在父 setState 之后,子状态对象被替换(initState)而不是更新(didUpdateWidget)