缓存子小部件与重新创建它们

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 应用程序,而无需缓存单个小部件。 我同意。这个问题不是关于我在开发中遇到的具体问题,而是关于框架的工作原理。对我来说,“大大提高效率”也表明性能得到了很大的提升。

以上是关于缓存子小部件与重新创建它们的主要内容,如果未能解决你的问题,请参考以下文章

Qt 缩放/缩放 QFrame 的内容(小部件等)

隐藏子小部件时,QGridLayout 未调整大小或重新绘制

创建一个函数来放置子小部件

具有重叠子小部件的 Qt 自定义小部件

如何将 QStackedWidget 大小设置为子小部件的最小尺寸?

在子创建后设置父时,子小部件对事件是透明的