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 会比较 runtimeTypekey 以了解是否应该保留前一个小部件的状态。然后 Flutter 在该小部件上调用 build

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

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

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

【讨论】:

"比较使用 == build 方法返回的先前和新的小部件",U 意思是 build 方法已经被调用。然后在“== 为假”条件下再次说“颤振调用建立在该小部件上”。你到底在说哪个小部件,你能指出父小部件和子小部件吗?请用一个小例子详细说明。

以上是关于setState() 如何重建子部件?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 setState 在颤振中重建

在父 setState 之后,子状态对象被替换(initState)而不是更新(didUpdateWidget)

Provider 和 setstate 哪个更贵?

Flutter - setState 不更新内部有状态小部件

Flutter setState 重建整页功能

除了 setstate 颤振之外,如何在小部件构建中获取值