缓存子小部件与重新创建它们
Posted
技术标签:
【中文标题】缓存子小部件与重新创建它们【英文标题】:Caching child widgets vs. recreating them 【发布时间】:2021-05-10 06:18:12 【问题描述】:我不确定是否缓存小部件实例并在 build()
方法中重用它会产生重大影响。
假设我们有两个小部件类:
class ParentWidget extends StatelessWidget
ParentWidget(Key key)
: super(key: key);
@override
Widget build(BuildContext context)
return Container( // or some other widgets that define the ui
child: ChildWidget(/*...*/),
);
class ChildWidget extends StatelessWidget
ChildWidget(Key key) : super(key: key); // no constant
@override
Widget build(BuildContext context)
/*
* returns some Widget
*/
据我了解,每次 Flutter 在ParentWidget
上调用build()
时,都会创建一个新的ChildWidget
并将其附加到元素树中的同一个元素上。除非const ChildWidget
可用(例如ChildWidget
有一个 const 构造函数)。
但是,我们可以像这样缓存孩子:
class ParentWidget extends StatelessWidget
final Widget child;
ParentWidget(Key key)
: child = ChildWidget(/*...*/),
super(key: key);
@override
Widget build(BuildContext context)
return Container(
// or some other widgets that define the ui
child: child, // <-- use child instead of ChildWidget()
);
据我了解,将使用相同的小部件,并且不必通过颤振来修改元素树。但我不确定在哪些情况下重要。
缓存小部件和创建具有相同配置的新小部件之间是否存在显着差异? 如果是这样,是否有关于何时缓存小部件而不是重建它们的规则?
【问题讨论】:
【参考方案1】:在StatefulWidget的文档中,如果该widget所代表的子树没有改变,建议缓存该widget:
如果子树没有改变,缓存代表该子树的小部件并在每次可以使用时重新使用它。与创建新的(但配置相同的)小部件相比,重用小部件效率大大提高。将有状态部分分解到一个接受子参数的小部件中是一种常见的方法。
因此,我得出结论,每当 Widget 更改状态时,应缓存并重用不根据状态更改的子树。
但是,问题中声明的示例并不是选择缓存小部件的好选择,因为只有不变子树的根应由该子树的父级缓存。但是由于ParentWidget
本身就是StatelessWidget
,所以每次ChildWidget
都是一个不变的子树的一部分。因此,ParentWidget
的一些有状态的 Parent 应该负责缓存。
【讨论】:
【参考方案2】:可能会有所不同,例如,如果子小部件分配资源或具有较大的子子树。
flutter api 官方文档确实建议在某些情况下进行缓存。但一般来说,在尝试优化视图时,它不应该是首先要做的事情。
阅读有关Stateful 和Stateless 小部件的文档,特别是“性能注意事项”部分有很多相关的进一步信息。例如:
如果子树未更改,则缓存代表该子树的小部件,并在每次可以使用时重新使用它。 尽可能使用 const 小部件。 (这相当于缓存一个小部件并重新使用它。)
【讨论】:
感谢您,我在StatefulWidget 的文档中找到了相关部分。他们建议在子树不更改时对其进行缓存,因为“与创建新的(但配置相同的)小部件相比,重用小部件的效率要高得多”。 不过,在许多情况下,您可以通过其他方式优化渲染。我已经制作了 Flutter 应用程序,而无需缓存单个小部件。 我同意。这个问题不是关于我在开发中遇到的具体问题,而是关于框架的工作原理。对我来说,“大大提高效率”也表明性能得到了很大的提升。以上是关于缓存子小部件与重新创建它们的主要内容,如果未能解决你的问题,请参考以下文章
隐藏子小部件时,QGridLayout 未调整大小或重新绘制