我是新手,我真的很想知道当我们调用setState时是否重新构建所有小部件的子树。
此处的子树是指该小部件下面的所有小部件树(包括该小部件作为根节点)。
当我们调用setState
函数时,将在子树的build
上调用root node
方法,这将触发其子级上的build方法。说出子树(该小部件的子代)的分支(此处为MyWidget1
)与状态变量无关。我注意到甚至在父节点中调用的setState
上也重建了独立的分支。
class _MyAppState extends State<MyApp> {
int count=0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[ MyWidget1(),MyWidget2(count),],),
floatingActionButton: FloatingActionButton(onPressed: ()=>setState((){count++;}),),
);
}
}
class MyWidget1 extends StatelessWidget {
@override
Widget build(BuildContext context) { print("widget builds 1");
return Container(height: 100, color: Colors.orange,);
}
}
class MyWidget2 extends StatelessWidget {
final int count;
MyWidget2(this.count);
@override
Widget build(BuildContext context) { print("widget builds 2");
return Text(count.toString());
}
}
在这里我们可以看到MyWidget1
独立于状态变量(此处为count
),因此通常setState
对它没有影响。
我想知道是否应该进行优化以避免在调用MyWidget1
函数时无用的setState
构建。由于MyWidget1
下的树可能太大,因此也将再次对其进行重建。
我的问题:
此独立小工具(此处为MyWidget1
)是否可以在setState
上再次构建?
是否有更好的方法来处理这种情况,以免重新生成。
注意:我已阅读此question
在这个问题中,有一种方法可以通过在build方法之外创建独立分支的实例来避免无用的构建
我的疑问是:
这是处理这种情况的方法还是其他更好的方法,或者由于在O(n)时间内建立树,这种情况根本就没有那么大(我认为这不是答案,因为构建树可能是O(n)操作,但其中可能包含许多耗时的操作,一次又一次无用地调用可能对优化不利。)
答案 0 :(得分:3)
是的,MyWidget1
是在该setState
的基础上重建的。只需相信代码即可。调用setState
之后,将调用build
,这将调用MyWidget1
的构造函数。在每个setState
之后,将重建整个子树。旧的小部件被丢弃。但是,国家并没有被抛弃。状态实例存在,不会重新创建(请参见didUpdateWidget)。
是的,是的。在每个setState
之后,将重建整个子树。
没关系,不用担心。
此处的窗口小部件类是非常轻量级的类。 Dart的垃圾收集器经过优化,可以实例化许多此类对象并将它们丢弃在一起。
您需要一次又一次地重新创建这棵树,只是一个外观。还有另外两个并行树,它们不是轻量级的,也不会重新创建。将您的窗口小部件树进行比较,以查找系统应如何修改实际ui元素。
为什么所有这些麻烦,您可能会问。因为创建树很容易,维护树很困难。这种反应式声明框架使我们仅创建树而不维护树就可以摆脱。
关于Flutter内部的一些资源,您可以阅读更多有关此内容。该视频之一就是这样的资源:https://www.youtube.com/watch?v=996ZgFRENMs
答案 1 :(得分:0)
class _MyAppState extends State<MyApp> {
int count=0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: <Widget>[ const MyWidget1(),MyWidget2(count),],),
floatingActionButton: FloatingActionButton(onPressed: ()=>setState((){count++;}),),
);
}
}
class MyWidget1 extends StatelessWidget {
const MyWidget1();
@override
Widget build(BuildContext context) { print("widget builds 1");
return Container(height: 100, color: Colors.orange,);
}
}
class MyWidget2 extends StatelessWidget {
final int count;
MyWidget2(this.count);
@override
Widget build(BuildContext context) { print("widget builds 2");
return Text(count.toString());
}
}
当构造函数以“ const”关键字开头时, 您可以缓存并重复使用小部件。
在调用构造函数以初始化窗口小部件时,请使用“ const”关键字。通过使用“ const”关键字调用,当其他窗口小部件更改时,该窗口小部件不会重建 他们在树上的状态。如果您省略“ const”关键字,则每次父项 小部件重新绘制。