小部件函数和类之间的性能差异

2023-12-05

在这种情况下,关于重建小部件和性能方面,两个选项之间有什么区别?

小部件类:

class Dummy() extends StatelessWidget {
  const Dummy();

  @override
  Widget build(BuildContext context) {
    return const Text(„text“);
  }
}

选项1:

class Option1 extends StatelessWidget {
  const Option1();

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: const Dummy(),
    );
  }
}

选项2:

class Option2 extends StatelessWidget {
  const Option2();

  Widget createDummyWidget() {
    return const Dummy();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: createDummyWidget(),
    );
  }
}

将小部件拆分为方法是一种反模式

因此,举例来说,如果我们有一个看起来像这样的小部件:

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('Counter: $_counter'),
        Container(
          child: Column(
            children: [
              Text('Hello'),
              Row(
                children: [
                  Text('there'),
                  Text('world!'),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

如果使用函数小部件

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;

  Widget _buildNonsenseWidget() {
    return Container(
      child: Column(
        children: [
          Text('Hello'),
          Row(
            children: [
              Text('there'),
              Text('world!'),
            ],
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('Counter: $_counter'),

        // The deeply nesting widget is now refactored into a
        // separate method and we have a cleaner build method. Yay!
        _buildNonsenseWidget(),
      ],
    );
  }
}

那么问题到底是什么?

每当 _counter 的值发生变化时,框架就会调用 build 方法。这会触发我们的小部件重建自身。问题是每次 _counter 的值发生变化时都会调用 _buildNonsenseWidget() - 这最终会一遍又一遍地重建小部件树。 重建毫无意义 在这种情况下,没有理由重建特定的小部件树。

_buildNonsenseWidget() 返回的小部件树本质上是无状态的 - 我们只需要构建它一次。遗憾的是,由于 widget 树是通过 _buildNonsenseWidget() 方法构建的,因此每次父 widget 重建时,Flutter 框架都会重建它。

从本质上讲,我们在重建不需要重建的东西时浪费了宝贵的 CPU 周期。发生这种情况是因为从框架的角度来看,长构建方法和拆分为多个较小方法的构建方法之间没有区别。请注意,这只是一个简单的示例 - 这对更复杂的应用程序有更显着的影响。

拆分长构建方法 - 重新审视 这个问题的解决方案相对简单,尽管它会导致几行额外的代码。我们没有将构建方法拆分为更小的方法,而是将它们拆分为小部件 - 即 StatelessWidgets。

当我们重构前面的例子时,我们最终会得到这样的结果:

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('Counter: $_counter'),

        // The deeply nesting widget is now refactored into a
        // stateless const widget. No more needless rebuilding!
        const _NonsenseWidget(),
      ],
    );
  }
}

class _NonsenseWidget extends StatelessWidget {
  const _NonsenseWidget();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Text('Hello'),
          Row(
            children: [
              Text('there'),
              Text('world!'),
            ],
          ),
        ],
      ),
    );
  }
}

结论

不要将构建方法拆分为多个较小的方法,而是将它们拆分为 StatelessWidget。这样,您就不会多次重建静态部件树,而只会浪费 CPU 周期。当谈到优化 Flutter 应用程序的性能时,这可能是最容易实现的目标之一。

我用了这篇文章:https://iiro.dev/splitting-widgets-to-methods-performance-antipattern/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小部件函数和类之间的性能差异 的相关文章

  • 使用 enum.values() 与字符串数组相比,性能是否会受到影响?

    我正在使用枚举来替换String我的 java 应用程序 JRE 1 5 中的常量 当我在不断调用的方法中将枚举视为名称的静态数组时 例如 在渲染 UI 时 是否会对性能造成影响 我的代码看起来有点像这样 public String get
  • Java 11 中使用堆栈跟踪的速度明显慢于 Java 8

    我正在比较 JDK 8 和 11 的性能jmh https openjdk java net projects code tools jmh 1 21 当我遇到一些令人惊讶的数字时 Java version 1 8 0 192 vendor
  • 是否可以提高 Mongoexport 速度?

    我有一个 1 3 亿行的 MongoDB 3 6 2 0 集合 它有几个简单的字段和 2 个带有嵌套 JSON 文档的字段 数据以压缩格式 zlib 存储 我需要尽快将其中一个嵌入字段导出为 JSON 格式 然而 mongoexport 需
  • 基于代理的模拟:性能问题:Python vs NetLogo & Repast

    我正在 Python 3 中复制一小段 Sugarscape 代理模拟模型 我发现我的代码的性能比 NetLogo 慢约 3 倍 这可能是我的代码的问题 还是Python的固有限制 显然 这只是代码的一个片段 但 Python 却花费了三分
  • 为什么 Python 中的无分支函数和内置函数速度较慢?

    我发现了 2 个无分支函数 它们可以在 python 中查找两个数字的最大值 并将它们与 if 语句和内置 max 函数进行比较 我认为无分支或内置函数将是最快的 但最快的是 if 语句函数 有人知道这是为什么吗 以下是功能 If 语句 2
  • Flutter无法从url加载图像

    图片资源服务捕获异常 解析图像编解码器时抛出以下 ImageCodecException 加载网络图像失败 图片网址 https cdn sportmonks com images soccer leagues 5 png https cd
  • try-catch 块是否会降低性能[重复]

    这个问题在这里已经有答案了 This link http www cplusplus com doc tutorial exceptions states 为了捕获异常 我们必须将一部分代码放在异常下 检查 这是通过将这部分代码包含在 tr
  • 如何解决“布局有超过 80 个视图,对性能不利”?

    我正在做一个有点复杂的布局 只是我无法修复 LINT 指示的错误 黑莓浏览次数超过 80 对性能不利 这是布局
  • Android Studio 无法运行 Xcode 模拟器

    我正在尝试使用 Xcode iPhone 模拟器模拟我的 Flutter 应用程序 但收到此错误 在升级 Android Studio 和 Xcode 之前 它运行良好 Launching lib main dart on iPhone X
  • 从后台恢复后,Flutter GoogleMap 为空白

    我遇到以下问题 我的 Flutter 应用程序使用 GoogleMap 地图最初加载得很好 但是 如果我将应用程序置于后台并稍后恢复 地图将保持空白 Google 徽标仍然显示 就像未指定 API 密钥时发生的情况一样 我的多边形叠加层也不
  • 快速查询最新记录的方法?

    我有一张这样的表 USER PLAN START DATE END DATE 1 A 20110101 NULL 1 B 20100101 20101231 2 A 20100101 20100505 在某种程度上 如果END DATE i
  • 在 Flutter 中从 Play 商店获取产品时应用内购买崩溃

    我在安装和实施后遇到问题应用内购买插件 https pub dev packages in app purchaseFlutter 团队提供 到目前为止我做了什么 在 Play 商店中添加了 2 个可见且活跃的产品 提交了用于 alpha
  • NoSuchMethodError:尝试调用非函数,例如 null:'dart.global.firebase.auth'

    Flutter 新手 我怀疑在尝试设置 Firebase Auth 时错过了一些非常简单的事情 一直在网上寻找解决方案 大多数人要求您仔细检查 firebase auth js 是否正确包含在 index html 文件中 这样就完成了 下
  • 更改项目名称

    Flutter项目的项目名称可以修改吗 项目名称是指您在创建 flutter 项目时提供的名称flutter create name 这取决于您想要实现的目标 如果您想更改手机菜单中显示的应用程序名称以及应用程序图标 则必须更改androi
  • 向上滚动时固定项目

    所以我有以下屏幕 我正在寻找一种方法 使得当用户向上滚动时 包含进度条和这 4 个数据字段 ItemHeader 的小部件将向上滚动 但搜索容器 SearchTextField 将被固定 到顶部 当然 当用户向下滚动时 它应该重新出现 我找
  • SignalR 似乎正在减慢我的 MVC/Azure 应用程序的启动速度

    我有一个 MVC 应用程序在 Windows Azure 上的 WebRole 上的 NET 4 5 下运行 使用 SignalR 1 0 alpha2 并使用 ServiceBus 底板 在我的 App Start 文件夹中 我有 Reg
  • Java 的 System.arraycopy() 对于小数组有效吗?

    是Java的System arraycopy 对于小数组来说是高效的 或者它是本机方法这一事实是否使其可能比简单的循环和函数调用效率低得多 本机方法是否会因跨越某种 Java 系统桥梁而产生额外的性能开销 稍微扩展一下 Sid 所写的内容
  • PostgreSQL 位图堆扫描索引非常慢,但仅索引扫描很快

    我创建了一个包含 43kk 行的表 并用值 1 200 填充它们 因此 表中每个数字大约为 220k create table foo id integer primary key val bigint insert into foo se
  • 使用属性和性能

    我正在优化我的代码 我注意到使用属性 甚至自动属性 对执行时间有深远的影响 请参阅下面的示例 Test public void GetterVsField PropertyTest propertyTest new PropertyTest
  • 发布Oracle和SQL Server性能测试是否违反许可? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想对Oracle和SQL Server中的空间索引进行性能测试 我想将其纳入我的理学硕士工作中 发布此类结果是否违反 dbms 的许可 也许有人已经

随机推荐

  • 在 Windows 上规范化路径时,Java 是否需要支持 ERROR_NO_MORE_FILES?

    问题 一些用 Java 实现的守护进程在 Windows 7 上运行 将文件从一个目录复制到另一个目录 而源目录和目标目录都是 Windows Server 2016 托管的网络共享 复制是使用 Apache Commons IO 完成的
  • 对于非 ASCII 字符串,UrlHelper.IsLocalUrl 方法始终返回“false”

    我最近发现 UrlHelper IsLocalUrl方法总是返回false 如果它检测到非 ASCII 字符url范围 Example var isLocal UrlHelper IsLocalUrl false 这是一个错误 还是 设计使
  • 什么是“运行时”?

    我听说过 C Runtime Visual C 2008 Runtime NET Common Language Runtime 等 什么是 runtime 确切地 它是什么做的 它如何与我的代码交互 或者更准确地说 它是如何控制我的代码的
  • 如何在catch中打印错误

    catch let error as LocksmithError print error it would print the case of the error 但是如果我这样做 catch LocksmithError Duplica
  • 如何更改表格的字体大小

    我正在画一张桌子matplotlib axes Axes table像这样 sub axes table cellText table vals colWidths 0 15 0 25 rowLabels row labels loc ri
  • PubSub REST 订阅拉取未返回所有消息

    我们使用要拉取的 REST 服务 API来自 PubSub 订阅的消息 准备好接受服务的消息被确认 而其他消息则在稍后的执行周期中未被确认而需要接受服务 在执行周期中 我们发送一个single请求给pull服务 REST API with
  • SPARQL 过滤器语言(如果可能)在多值上下文中

    考虑以下来自 GeoNames 数据库的摘录 prefix gn
  • 适用于 iPhone 的地理空间库

    我正在考虑创建一个位置感知 iPhone 应用程序 该应用程序可以通过与兴趣点 POI 列表打包来离线工作 该应用程序将从中读取用户的当前位置CoreLocation并按照距用户当前位置的远近顺序生成 POI 列表 我需要两个基本的地理空间
  • ImageView 拒绝父级的圆角和边框

    我有一个有多个孩子的视图 我想给整个组圆角 如下所示 我试图通过给父 LinearLayout 及其 ImageView 通过背景提供圆角来做到这一点 LinearLayout 和子级
  • 在 Swift 4 中从 InputStream 中准确读取 n 个字节

    我有一个通过 TCP 向我发送消息的服务器 其中前 4 个字节确定消息其余部分的长度 所以我需要 1 将4个字节读入UInt32 有效 并将其存储到预期字节数 2 read 预期字节数字节到message 现在我的代码如下所示 privat
  • 部分细胞进料负载

    各位新年快乐 目前 我正在使用以下默认方式访问和加载 Google 表格工作表 URL metafeedUrl new URL SPREADSHEET URL SpreadsheetEntry spreadsheet service get
  • 单元测试和检查私有变量值

    我正在使用 C NUnit 和 Rhino Mocks 编写单元测试 以下是我正在测试的课程的相关部分 public class ClassToBeTested private IList insertItems new List publ
  • 放弃 C++20 中显式函数模板特化的访问检查规则

    温度规格 6通过实现添加到 C 20P0692R1 专业化访问检查 emphasis mine 温度规格 6常用的访问检查规则不适用于声明中的名称显式实例化或明确的专业化 但出现在函数体 默认参数 基本子句 成员规范 枚举器列表或静态数据成
  • 我可以手动创建核心数据实体类的实例以供临时使用吗?

    我有一个核心数据实体的自定义类 称为 朋友 当我解析 XML 文件时 我需要创建临时实例来保存临时数据 此时不使用 Core Data 所以有两个选择 A 创建一个 NSMutableDictionary 来保存临时数据 同时从 XML 解
  • “&&”在这个批处理文件中起什么作用?

    我收到了回答我一个问题的人发来的一行代码 但我很困惑 在这个批处理文件中做什么 echo off set p Quest How are you today echo Quest gt Results txt findstr r i not
  • 在 python 中绘制使用 matplotlib 分段定义的函数

    我正在尝试绘制我分段定义的函数 举个例子 以 def f x y if x in I open 0 1 if y in I open 0 1 return x y else return 0 然后我将 Z 定义如下 X np arange
  • Java 10 下的 Eclipse Window Builder 错误

    Eclipse 在 0 下运行 但该 Java 项目的 Java 合规级别为 10 因此 WindowBuilder 将无法从该项目加载类 对项目使用较低级别的 Java 或使用较新的 Java 版本运行 Eclipse 这是我安装窗口生成
  • 缩小时 OSMDroid 崩溃

    我在我的应用程序中添加了一个 OSMDroid 地图 它工作正常 但如果我缩小 它就会崩溃 我在用户当前位置加载地图时添加了一个项目 并在加载地图后在 AsyncTask 中再加载 10 个项目 更新 工作解决方案 在下面的旧代码中 我在用
  • 块中的WeakSelf

    有一个关于弱自我 阻塞和保留周期的问题 通过这本书 我明白我们需要在块中使用weakself 问题是 什么时候 例如 简单的动画代码 永远不要包含weakself i e self myView alpha 1 0 UIView anima
  • 小部件函数和类之间的性能差异

    在这种情况下 关于重建小部件和性能方面 两个选项之间有什么区别 小部件类 class Dummy extends StatelessWidget const Dummy override Widget build BuildContext