Flutter 小技巧之为什么推荐 Widget 使用 const

今天收到这个问题,本来想着简单回复下,但是感觉这个话题又可以稍微展开讲讲,干脆就整理成一篇简单的科普,这样也能更方便清晰地回答这个问题。

聊这个问题之前,我们需要把一个“老生常谈”的概念拿出来说,那就是:Flutter 里 Widget 是不可变的,它不是真正的 View,Widget 只是一个「配置文件」的作用

后面只有基于这个概念,结合 const 的「深度不变性」 ,才能更全面理解为什么 Flutter 中推荐 Widget 使用 const 。

Dart 里的 final & const

我们先简单过一遍 Dart 里的 final 和 const 的区别,要解答开头那个问题,只讲 const 明显是不够,在 Dart 里:

  • final :变量只能赋值一次,值在运行时确定

  • const:变量必须是编译时常量,值在编译时已知

虽然都是「不可变」声明,但是对于 Dart 来说,final 和 const 最大的区别就在于一个是运行时确定,一个是编译时确定。

final

针对 final , final 虽然也不可变 ,但是它的值可以在运行时确定,同时它还允许延迟初始化(late),如下代码所示:

  • 变量 a 可以是 late final
  • result 的数可以是通过 doSomeThing 返回
late final String a;

void runResult() {
 final int result = doSomeThing(); 
} 

也就是 final 可以在运行时赋值,之后就不可以改变,类似场景就可以对应在 Widget 的构造函数上,通过 final 关键字创建不可变的实例变量,这些变量在构造函数级别初始化,并且对于每个类实例都是唯一的:因为 Flutter 里 Widget 是不可变的,所以对于 Widget 来说,它内部的变量也应该是不可变

class MyHomePage extends StatelessWidget {
  MyHomePage({super.key, this.title});
  final String? title;
}

const

const 属于编译时不可变声明,可以理解为它是比 final 更高级的 「深度不变」,也就是编译时就确定了它的值,所以它会有更好的性能优势,例如:

  • 作为编译时常量的, const 变量在编译时已知,因此它在编译期间只会被“评估”一次,这意味着 Dart 编译器可以对它们进行优化,从而节省内存并缩短需要的启动时间
  • 当 const 变量在不同位置使用时,Dart 编译器只会给它分配一次空间,并且该值将在引用它的其他位置重复使用。

从这个角度理解,const 确实可以一定程度提高性能和节约内存 ,再举个典型例子解释下 「深度不变」,如下代码所示:

可以看到通过 const 声明的 list, 它内部的 item 也是在编译时确定,并且是不允许被修改,不仅列表本身是一个编译时常量,它内部每个元素也是编译时常量。

const List<int> list = [0,0,0,0,0,0];

list[2] = 3;

而对于 class 而言,const 声明的构造函数,会被要求内部变量需要使用 final 声明,从而确保对象是可传递的不可变的,这样就可以保证静态数据的完整,并且对象一旦设置就无法被篡改。

class Test {
 final int a;
 const Test(this.a);
}

void runTest() {
 const Test test = Test(0);
 test.a = 100;  /// error
} 

这个看起来是不是很眼熟?对,没错,就是 Flutter 里的 Widget,当 Widget 的构造函数是 const 的时候,它内部的变量都需要时 final ,不然就会在编译时报错。

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, this.title});
  final String? title;
}

如果没有 const ,默认规则下只会是警告:This class (or a class that this class inherits from) is marked as ‘@immutable’, but one or more of its instance fields aren’t final

另外,const 声明的构造函数,对于 class 来说也会在编译时优化,如下代码所示,可以看到它们都在编译期得到了优化:

  • test 1 和 test 2 的 hashCode 是一样的
  • test 3 和 test 4 的 hashCode 是一样的
  class Test {
    final int a;
    final int b;

    const Test(this.a, this.b);
  }

  void runTest() {
    const Test test1 = Test(0, 0);
    print("test1 hash code is: ${test1.hashCode}");
    const Test test2 = Test(0, 0);
    print("test2 hash code is: ${test2.hashCode}");
    const Test test3 = Test(1, 1);
    print("test3 hash code is: ${test3.hashCode}");
    const Test test4 = Test(1, 1);
    print("test4 hash code is: ${test4.hashCode}");
    const Test test5 = Test(2, 2);
    print("test5 hash code is: ${test5.hashCode}");
  }

Flutter

那么回到最初的问题,因为 Flutter 里的 Widget 不是真正的 View ,它只是个配置文件,背后是 Element 和 RenderObject 实体在工作,所以对于「不可变」的 Widget 来说,const 去声明一个「配置文件」做优化,明显可以提高性能和减少内存占用。

至于为什么说 Widget 不是真正的 View , 详细的可以看我以前的文章,这里简单展示一个我经常提到的例子,如下代码所示,textUseAll 如果是一个真正的 View ,它是不能同时被多个地方添加,从这个例子可以更直观体现 Widget 是配置信息的作用。

对于 Flutter 来说,Flutter 会严重依赖 Widget 树的 「配置信息」来表示 UI,在 rebuild 期间遇到标记为const 的 Widget 时,Flutter 会将其识别为预构建且不可变的对象 ,这个情况下, Flutter 可以重复使用现有对象,而不必创建新对象,这种重复使用可避免不必要的计算和对象分配。

同时前面提到过,const 在编译时会执行优化,这些优化包括前面提到的预分配内存和常量折叠,这意味着在运行时可以更快地创建对象并减少垃圾回收触发。

另外,对于 Widget Tree 来说,const 可以确保只有当它们的引用实际发生变化时才会 rebuild,进而减少了不必要的 Widget 创建和重构。

所以,是不是无用知识又增长了?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/748807.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安宝特方案 | AR眼镜+手套式扫码枪,智能化仓储创新应用

新扫码设备形态&#xff0c;提升工作效率 传统的仓储工作通常依赖人工操作和纸质记录&#xff0c;这不仅耗时又容易出错。 引入穿戴式AR设备和手套式扫码枪后&#xff0c;AR眼镜可以将数字信息直接叠加在视野中&#xff0c;仓储工人只需佩戴设备即可看到货物位置、库存数量和任…

3. 向索引库中导入数据

1. 准备数据库对象 import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstr…

高校外卖点餐系统

摘 要 随着互联网的快速发展&#xff0c;外卖点餐已经成为人们生活中的一部分。为了满足高校学生的需求&#xff0c;本文设计和实现了一个基于Java Web的高校外卖点餐系统。该系统采用B/S架构&#xff0c;使用Java语言和SSM框架进行开发&#xff0c;前端使用Vue框架进行设计。…

idea中使用springboot进行开发时遇到的工程结构问题汇总

idea中的工程结构和eclipse中不同&#xff0c;但是配置的内容都是一样的。 IDEA中也就是这个页面&#xff0c;快捷键ctrlaltshifts 如果在eclipse中&#xff0c;经常会遇到jre和jdk不正确的情况&#xff0c;但IDEA中这个问题很少&#xff0c;但是IDEA中会经常由于未正常配置根…

基于SpringBoot音乐网站与分享平台详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; Java精品实战案例《600套》 2023-2025年最值得选择的Java毕业设计选题大全&#xff1…

浅谈逻辑控制器之仅一次控制器

浅谈逻辑控制器之仅一次控制器 “仅一次控制器”(Once Only Controller) 是一个非常实用的组件&#xff0c;它允许用户控制测试计划中的某些操作仅执行一次&#xff0c;无论其所在的线程组或父级控制器设置了多少次循环。本指南将详细介绍“仅一次控制器”的功能、使用场景及配…

RSA非对称加密-openssl命令及C语言实现

RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。本文介绍如何使用openssl命令和C代码实现基础的RSA加/解密和签名/验签功能。 一、openssl命令实现RSA加解密 1、生成私钥和公钥 生成私钥 openssl genrsa -out private.key 2048 #…

『Z-Workshop』 6月22日线下ALCOVE分享活动

2024 求是创新 ZJUBCA Sponsored by the ALCOVE Community TIME&#xff1a;2024/06/22 ADD&#xff1a;浙江大学紫金港校区 --- Alcove 是 Aptos 公链与 Alibaba Cloud 共同打造的亚洲首个 Move 开发者社区&#xff0c;致力于支持开发者使用 Move 语言构建下一代 Web3 应用&am…

UE4_材质_水涟漪、水深制作_Ben教程

学习笔记&#xff0c;不喜勿喷&#xff01;侵权立删&#xff0c;祝愿生活越来越好&#xff01; 效果图如下&#xff1a; 创建水材质的教程&#xff0c;首先需要外出收集一些参考&#xff0c;看一看你将要做的事情很重要&#xff0c;确定将要模仿物体的关键属性&#xff0c;从这…

Java网络编程(JavaWeb的基础)

Java网络编程&#xff08;JavaWeb的基础&#xff09; 文章目录 Java网络编程&#xff08;JavaWeb的基础&#xff09;前言一、网络编程概述1.1 软件架构&网络基础1.2 网络通信要素:IP/端口/通信协议1.3 传输层协议:tcp/udp 二、网络编程API2.1 InetAddress类2.2 Socket类&am…

第三届人工智能、物联网与云计算技术国际会议(AIoTC 2024)

第三届人工智能、物联网与云计算技术国际会议(AIoTC 2024)将于2024年9月13日-15日在中国武汉举行。本次会议由华中师范大学伍伦贡联合研究院与南京大学联合主办、江苏省大数据区块链与智能信息专委会承办、江苏省概率统计学会、江苏省应用统计学会、Sir Forum、南京理工大学、南…

如何找到正确的网络钓鱼目标

在深入研究联系人收集之前&#xff0c;我们希望确保对可用的攻击面有一个清晰的了解。我见过许多渗透测试者只获取客户端提供的主域&#xff0c;通过 theHarvester、linkedInt、maltego 等运行它&#xff0c;并将输出称为目标列表。在这样做的过程中&#xff0c;这些渗透测试机…

云效BizDevOps上手亲测

云效BizDevOps上手亲测 什么是云效项目协作Projex配置2023业务空间原始诉求字段原始诉求工作流创建原始诉求配置2023产品空间创建主题业务原始诉求关联主题配置2023研发空间新建需求需求关联主题 与传统区别云效开发流程传统开发流程云效BizDevOps 操作体验 什么是云效 在说到…

203. 移除链表元素【链表】【C++】

题目描述 题目描述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#x…

Labview_Occurrencel(事件发生)

PS&#xff1a;这里遇到 一个很Low的事情&#xff1a; 在停止第二个while循环的时候出现了停止不了的情况。因为等待事件发生设置的超时时间为:-1。所以等事件发生后出现了条件接线端已经执行的情况&#xff0c;所以当下次事件发生时未能及时停止。初版的停止设置如下图&#x…

AI赋能视频剪辑师:人工智能时代,视频剪辑师该如何剪辑?

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;视频剪辑行业也不例外。在这个全新的时代&#xff0c;AI技术为视频剪辑师带来了前所未有的便利和创新空间。那么&#xff0c;在人工智能时代&#xff0c;视频剪辑师…

红海云签约联东集团,引领产业园区领军企业人力资源数字化新范式

北京联东投资&#xff08;集团&#xff09;有限公司&#xff08;以下简称“联东集团”&#xff09;是集产业园区运营、模板钢结构和投资业务为一体的集团化公司。联东集团独创了产业聚合U模式&#xff0c;致力于打造产业集聚平台&#xff0c;服务于实体企业成长和地区经济发展。…

数据结构与算法笔记:高级篇 - 向量空间:如何实现一个简单的音乐推荐系统?

概述 很多人喜都喜爱听歌&#xff0c;以前我们用 MP3 听歌&#xff0c;现在直接通过音乐 App 在线就能听歌。而且&#xff0c;各种音乐 App 的功能越来越强大&#xff0c;不仅可以自己选歌听&#xff0c;还可以根据你听歌的喜好&#xff0c;给你推荐你可能会喜好的音乐&#x…

文件安全存储面临的三大困扰?企业可轻松一键解决

企业文件存储是企业生产经营要解决的基础性问题&#xff0c;一般来说&#xff0c;企业常见的文件存储方式有如下几种&#xff1a; 直接附加存储&#xff08;DAS&#xff09;&#xff1a; 特点&#xff1a;数据备份和恢复会占用服务器主机资源&#xff08;如CPU、系统IO等&…

推荐一个shp修复工具

我们在《如何解决ArcGIS中数据显示乱码问题》一文中&#xff0c;为你分享过打开shp文件的乱码问题。 现在再为你分享一个shp文件的修复工具&#xff0c;你可以在文末查看该工具的领取方式。 shp文件修复工具 Shapefile&#xff08;简称SHP&#xff09;是Esri推出的一种广泛使…