当前位置: 首页 > article >正文

Flutter 启动优化

Dart VM在Flutter中的作用是什么?它负责执行Dart代码,无论是JIT还是AOT模式都需要它。在JIT模式下,VM随应用一起运行,而在AOT模式下,代码已经被编译成机器码,VM可能不需要运行时存在?不过实际上,即使在AOT模式下,某些功能可能仍需要VM的支持,比如动态加载或某些平台特定的操作。

用户提到的“预初始化”可能是指在应用启动前预先准备好VM环境,以减少冷启动时间。这在JIT模式下尤其重要,因为每次启动都需要加载VM并编译代码。预初始化可能涉及提前加载VM、共享VM实例或者复用之前的VM状态。

Dart VM 的作用

  1. 代码执行:负责解析、编译和执行 Dart 代码。
  2. 内存管理:自动处理垃圾回收(GC)。
  3. 运行时服务:提供反射、类型检查、异步调度等功能。
  4. 插件交互:通过 Platform Channel 与原生代码通信。

Dart虚拟机的创建过程

Dart虚拟机是一个解释器,它可以将Dart代码编译成字节码,并通过解释器将其转换成机器码并执行。在Flutter应用程序中,Dart虚拟机是通过Flutter引擎来创建和运行的。

下面是Dart虚拟机的创建过程:

  1. 首先,Flutter引擎会创建一个新的Isolate(独立的Dart执行环境),并将Dart代码加载到该Isolate中。
  2. 接着,Flutter引擎会启动Dart虚拟机,并为该Isolate创建一个Dart虚拟机实例。
  3. Dart虚拟机实例会初始化一个Dart运行时环境,并在该环境中创建一个Isolate对象,该对象用于管理和控制当前的执行环境。
  4. Dart虚拟机实例会为该Isolate分配一些资源,包括栈空间、堆内存和文件描述符等。
  5. Dart虚拟机实例会将Dart代码编译成字节码,并将其加载到该Isolate中。
  6. 然后,Dart虚拟机实例会创建一个Dart解释器,该解释器会解释和执行该Isolate中的Dart代码。
  7. 最后,Dart虚拟机实例会启动该Isolate,从而开始执行Dart代码。

1. 启动速度优化

Flutter启动流程:

1). 一个Native进程只有一个DartVM

2). 第一个FlutterEngine初始化时,会创建并初始化DartVM

3). 一个DartVM可以有多个FlutterEngine,每个FlutterEngine都运行在自己的Isolate中,他们的内存数据不共享,需要通过Isolate事先设置的port(顶级函数)通讯。

作者:淘淘养乐多
链接:https://juejin.cn/post/7350868887322263552
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一、启动阶段的核心问题

1. 冷启动(Cold Start)

  • 定义:应用首次启动时,需要完成从 Dart VM 初始化加载核心框架代码解析资产文件 到 渲染首屏界面 的完整流程。
  • 关键瓶颈
    • Dart VM 启动:初始化虚拟机、加载基础库。
    • AOT 编译产物加载:解析编译后的二进制代码(如 app.so)。
    • 路由与初始化逻辑:执行 main() 函数中的业务代码。
    • 资源解析:加载字体、图片、本地化文件等。

2. 热启动(Hot Restart)

  • 定义:在已运行的 VM 上重启应用(如通过 flutter run 时的热重载)。
  • 优化重点:复用 VM 和大部分已加载的代码/资源。

二、底层优化原理

1. AOT 编译(Ahead-Of-Time)

原理
  • 将 Dart 源码 静态编译 为 目标平台的机器码(如 x86_64、ARM64),生成 app.so(Linux/macOS)或嵌入到二进制包中(Android/iOS)。
  • 对比 JIT(Just-In-Time)
    • JIT 启动时动态编译代码,但会引入编译开销;AOT 启动时直接执行机器码,无编译延迟。
优化效果
  • 冷启动时间减少 30%~50%(尤其是复杂应用)。
  • 内存占用降低:无需维护 JIT 编译器堆栈。
实现细节
  • Dart VM 启动流程
    1. 加载 AOT 编译后的 vm isolate(包含基础 VM 运行时)。
    2. 加载 root isolate(包含应用代码的字节码或 AOT 机器码)。
    3. 执行 main() 函数。

2. Tree Shaking

原理
  • 通过 静态分析,移除未使用的代码(函数、类、变量)。
  • 实现方式
    • Dart 编译器:在 aot 模式下自动标记未引用代码。
    • 构建工具:Gradle(Android)和 CocoaPods(iOS)集成 Tree Shaking。
优化效果
  • 包体积减少 10%~30%(例如移除未使用的第三方库功能)。
  • 启动时间间接优化:减少需加载的代码量。

3. Dart VM 初始化优化

关键机制
  • VM 预初始化
    • 在某些嵌入引擎(如 Flutter Engine)中,VM 可能在应用启动前预先初始化。
    • Android 示例:通过 flutter.startInitialization 提前加载 VM。
  • ** isolates**:
    • main isolate 负责业务逻辑,vm isolate 负责运行时服务(如垃圾回收)。
    • 优化方向:减少 main isolate 启动时的初始化开销。

三、具体优化措施

1. 代码优化
(1) 精简 main() 函数
  • 问题:复杂的 main() 函数会触发大量初始化逻辑。
  • 优化方案
     
    void main() async {// 延迟初始化非核心服务(如 Firebase)await Firebase.initializeApp();runApp(const MyApp());
    }
  • 原理:将耗时操作(如网络请求、第三方库初始化)延迟到首屏渲染之后。
(2) 按需加载路由
  • 问题:传统路由模式会在启动时注册所有页面。
  • 优化方案
     
    // 使用动态路由注册
    final router = FlutterNativeRouter();
    router.defineRoute('/login', LoginScreen());
    // 在需要时注册路由
    await router.registerRoutes();
    runApp(MyApp());
  • 原理:按需加载路由,避免一次性注册所有页面。
(3) 移除未使用的代码
  • 工具
    • flutter analyze:检测未使用的变量、函数。
    • pub deps:查看依赖树,移除冗余库。

2. 配置优化
(1) 启用 AOT 并关闭调试模式
  • Android (build.gradle)
     
    flutter {target: lib/main.dartaot: truedebugEnabled: false
    }
  • iOS (ios/Runner/Info.plist)
     
    <key>FLUTTER_ENABLE_AOT</key>
    <true/>
    <key>FLUTTER_DEBUG_MODE</key>
    <false/>
  • 原理:AOT 编译减少启动时的 JIT 开销,关闭调试模式禁用断言和日志。
(2) 调整 Dart VM 参数
  • Android (build.gradle)
     
    flutter {dartOptions {vmArguments: --no-sound-null-safety}
    }
  • 原理:关闭 sound null safety 可加速非空安全模式的检查。

3. 构建优化
(1) 启用持久化构建缓存
  • 命令行
     
    flutter clean
    flutter build --cache
  • 原理:复用构建缓存,避免重复编译相同的依赖。
(2) 使用 Split APKs(Android)
  • 配置
     
    android {splits {abi {enable truereset()include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'}}
    }
  • 原理:为不同 CPU 架构生成独立的 APK,减少包体积。

4. 资源优化
(1) 压缩与子集化资源
  • 图片压缩
    • 使用 WebP 格式(透明度支持更好)或 PNG8(无透明度)。
    • 工具:TinyPNG、ImageOptim。
  • 字体子集化
     
    fonts:- family: Robotosubsets: latin
  • 原理:减少资源文件体积,加快加载速度。
(2) 按需加载 Assets
  • 动态加载
     
    Future<void> loadAssets() async {await rootBundle.load('assets/large_image.png');
    }
  • 原理:首屏加载完成后按需加载非关键资源。

5. 平台特定优化
(1) Android 优化
  • 移除冗余主题
     
    <!-- AndroidManifest.xml 中移除默认主题 -->
    <applicationandroid:theme="@style/Theme.AppCompat.Light.NoActionBar">
    </application>
  • 启用代码混淆与 ProGuard
     
    buildTypes {release {minifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}
    }
  • 原理:混淆代码可减少逆向工程风险,同时 Tree Shaking 依赖 ProGuard 规则。
(2) iOS 优化
  • 移除调试符号
     
    post_install do |installer|installer.pods_project.targets.each do |target|target.build_configurations.each do |config|if config.name == 'Debug'config.build_settings['ENABLE_BITCODE'] = 'NO'endendend
    end
  • 使用 strip_unused_code
     
    flutter build ios --release --strip-unused-code
  • 原理:移除未使用的符号和代码,减小可执行文件体积。

四、性能分析工具

1. Flutter DevTools
  • Timeline 视图
    • 分析启动阶段的各个阶段耗时(如 VM 初始化、Dart 初始代码加载、渲染首屏)。
  • CPU Profiler
    • 检测启动时热点函数(如 main() 中的初始化逻辑)。
2. 命令行工具
  • flutter run --trace-skia
    • 输出 Skia 绘制指令,分析渲染性能。
  • flutter dump-tree
    • 查看渲染树结构,识别不必要的视图层级。

五、高级优化技巧

1. 冷启动预加载
  • 方案:在应用安装后立即启动一个后台进程,预加载核心数据。
  • 限制:可能违反平台政策(如 iOS 的后台执行限制)。
2. 使用 flet 或 flutter_native_router
  • 路由优化:通过声明式路由减少初始化开销。
  • 示例
     
    final router = FlutterNativeRouter();
    router.defineRoute('/home', (context) => const HomeScreen());
3. Dart VM 预初始化
  • Android:通过 flutter.startInitialization() 提前加载 VM。
  • iOS:在 AppDelegate 中手动初始化 Dart VM。

六、总结

优化分层

层级优化手段原理
编译层AOT、Tree Shaking减少代码量和编译开销
运行时层VM 初始化优化、按需加载资源减少启动时的初始化负担
构建层缓存、Split APKs减少构建产物体积
平台层ProGuard、代码混淆进一步压缩代码和资源

关键指标

  • 启动时间:从 main() 开始到首屏渲染完成的时间。
  • 包体积:通过 flutter build 生成的可执行文件大小。
  • CPU 占用:分析工具检测的启动阶段峰值 CPU 使用率。

通过上述优化,可将复杂应用的冷启动时间从 2~3 秒 缩短至 0.5~1 秒,显著提升用户体验。

相关文章:

Flutter 启动优化

Dart VM在Flutter中的作用是什么&#xff1f;它负责执行Dart代码&#xff0c;无论是JIT还是AOT模式都需要它。在JIT模式下&#xff0c;VM随应用一起运行&#xff0c;而在AOT模式下&#xff0c;代码已经被编译成机器码&#xff0c;VM可能不需要运行时存在&#xff1f;不过实际上…...

JavaScript数组方法reduce详解

JavaScript数组方法reduce详解 目录 JavaScript数组方法reduce详解一&#xff0c;前言二&#xff0c;核心语法三&#xff0c;案例1.求和2.找最大值3.数组转对象4.复合操作&#xff08;同时实现 map filter&#xff09; 四&#xff0c;常见错误1.空数组没有初始值2.没有返回累加…...

计算机毕业设计SpringBoot+Vue.js服装商城 服装购物系统(源码+LW文档+PPT+讲解+开题报告)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Web自动化中Selenium下Chrome与Edge的Webdriver常用Options参数

目录 引言 说明 Add_argument() 添加方式 常用参数 Add_experimental_option() 添加方式 常用方法 任务结束后仍然保持浏览器打开 禁用“Chrome 正受到自动测试软件的控制”提示 设置下载路径 禁用弹窗拦截 禁用图片加载 禁用 JavaScript 注意 引言 …...

现代未来派品牌海报徽标设计无衬线英文字体安装包 THANKS LAB

THANK LAB 是一种高级未来主义的软字体&#xff0c;将时尚的现代设计与光滑圆润的边缘相结合&#xff0c;营造出大胆而平易近人的美感。这款字体非常适合品牌、海报、标题、UI/UX 和科幻主题项目&#xff0c;旨在激发创造力。THANK LAB Futuristic Soft Font 完全支持拉丁字母、…...

《AI与NLP:开启元宇宙社交互动新纪元》

在科技飞速发展的当下&#xff0c;元宇宙正从概念逐步走向现实&#xff0c;成为人们关注的焦点。而在元宇宙诸多令人瞩目的特性中&#xff0c;社交互动体验是其核心魅力之一。人工智能&#xff08;AI&#xff09;与自然语言处理&#xff08;NLP&#xff09;技术的迅猛发展&…...

【算法通关村 Day6】二叉树层次遍历

树与层次遍历青铜挑战 理解树的结构 通过中序和后序遍历序列恢复二叉树是一个经典的二叉树构建问题。给定二叉树的中序遍历序列和后序遍历序列&#xff0c;我们可以利用以下步骤进行恢复。 思路&#xff1a; 后序遍历的特点&#xff1a; 后序遍历的最后一个节点是树的根节点…...

安全面试2

文章目录 简单描述一下什么是水平越权&#xff0c;什么是垂直越权&#xff0c;我要发现这两类漏洞&#xff0c;那我代码审计要注意什么地方水平越权&#xff1a;垂直越权&#xff1a;水平越权漏洞的审计重点垂直越权漏洞的审计重点 解释一下ssrf漏洞原理攻击场景修复方法 横向移…...

【JavaScript进阶】构造函数数据常用函数

目录 本章节用到的所有素材都可以找到&#xff1a;素材自取~~~~ 1、深入对象 1.1创建对象三种方式 1.2 构造函数 练习 利用构造函数创建多个对象 实例化执行过程 1.3实例成员&静态成员 2. 内置构造函数 2.1 Object 2.2 Array 练习 员工涨薪计算成本 2.3 St…...

在PiscTrace开发者版上直接处理图像色阶分布

在图像处理和计算机视觉中&#xff0c;色阶分布&#xff08;或称灰度分布&#xff09;是描述图像中像素强度分布的一个重要概念。它对于理解图像的亮度、对比度、纹理和细节等方面具有关键作用。通过色阶分布的分析&#xff0c;我们能够获得图像的整体信息&#xff0c;从而帮助…...

趣味数学300题1981版-十五个正方形

分析&#xff1a;移动两根变成11个正方形很简单&#xff1a; 移动4根变成15个正方形&#xff0c;分析&#xff1a; 一个田字格包含5个正方形&#xff0c;若要15个正方形需要3个田字格&#xff0c;如果3个田字格完全不重合&#xff0c;需要6*318根火柴。如果合并正方形的边&…...

Selenium实战案例1:论文pdf自动下载

在上一篇文章中&#xff0c;我们介绍了Selenium的基础用法和一些常见技巧。今天&#xff0c;我们将通过中国科学&#xff1a;信息科学网站内当前目录论文下载这一实战案例来进一步展示Selenium的web自动化流程。 目录 中国科学&#xff1a;信息科学当期目录论文下载 1.网页内…...

前端面试-JavaScript 数据类型检测全解

目录 一、基础检测方法 二、方法深度解析 1. typeof 运算符 2. instanceof 运算符 3. 终极检测方案 三、特殊场景检测方案 四、手写实现原理 1. 通用类型检测函数 2. 改进版数组检测&#xff08;兼容旧浏览器&#xff09; 五、常见面试陷阱 六、最佳实践指南 七、扩…...

nginx 反向代理 配置请求路由

nginx | 反向代理 | 配置请求路由 nginx简介 Nginx&#xff08;发音为“Engine-X”&#xff09;是一款高性能、开源的 Web 服务器和反向代理服务器&#xff0c;同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;于 2004…...

用户中心项目教程(十)---注册里面的重定向排查和相关的修改

文章目录 1.注册逻辑的设计和实现2.解决自带的这个重定向的问题3.增加属性的相关操作4.关于如何修改页面上面的绿色按钮 1.注册逻辑的设计和实现 上次说到了的是登录功能&#xff0c;我们使用数据库里面存在的这个存在的账户和密码进行登录&#xff0c;但是是无法进行跳转的&a…...

根据音频中的不同讲述人声音进行分离音频 | 基于ai的说话人声音分离项目

0.研究背景 在实际的开发中可能会遇到这样的问题&#xff0c;老板让你把音频中的每个讲话人的声音分离成不同的音频片段。你可以使用au等专业的音频处理软件手动分离。但是这样效率太慢了&#xff0c;现在ai这么发达&#xff0c;我们能否借助ai之力来分离一条音频中的不同的说…...

【单片机】【UDS】 (单帧与多帧) 数据传输

对于使用 CAN 的诊断通信系统&#xff0c;每个单帧 (SF)、 第一帧 (FF)、 连续帧 (CF) 或流控 制帧 (FC) 有 8 字节数据场&#xff1b;其中单帧的 CAN_DL≤8 且第一帧的 FF_DL≤4095&#xff1b;下表 中已定义 每个报文的类型。 CAN FD 帧的数据场支持最大 64 个字节&#xff0…...

WebXR教学 02 配置开发环境

默认操作系统为Windows 1.VS Code VS Code 是一款轻量级、功能强大的代码编辑器&#xff0c;适用于多种编程语言。 下载 步骤 1&#xff1a;访问 VS Code 官方网站 打开浏览器&#xff08;如 Chrome、Edge 等&#xff09;。 在地址栏输入以下网址&#xff1a; https://code.v…...

MySql数据库运维学习笔记

数据库运维常识 DQL、DML、DCL 和 DDL 是 SQL&#xff08;结构化查询语言&#xff09;中的四个重要类别&#xff0c;它们分别用于不同类型的数据库操作&#xff0c;下面为你简单明了地解释这四类语句&#xff1a; 1. DQL&#xff08;数据查询语言&#xff0c;Data Query Langu…...

网络协议相关问题

1. HTTP 与 HTTPS 的区别 HTTP&#xff1a;明文传输&#xff0c;端口80&#xff0c;无加密&#xff0c;易被窃听或篡改。HTTPS&#xff1a;SSL/TLS加密传输&#xff0c;端口443&#xff0c;通过数字证书验证身份&#xff0c;防止中间人攻击。 混合加密&#xff1a;非对称加密交…...

宇树科技13家核心零部件供应商梳理!

2025年2月6日&#xff0c;摩根士丹利&#xff08;Morgan Stanley&#xff09;发布最新人形机器人研报&#xff1a;Humanoid 100: Mapping the Humanoid Robot Value Chain&#xff08;人形机器人100&#xff1a;全球人形机器人产业链梳理&#xff09;。 Humanoid 100清单清单中…...

Windows 启动 SSH 服务报错 1067

Windows 启动 SSH 服务报错 1067 一、原本安装的 Windows 自带的 SSH 服务 按 Windows 键 -> 设置 -> 系统 -> 可选功能 在 添加的功能 查看是否安装了 OpenSSH 服务 一开始 执行 net start sshd 是可以正常启动的 并且其他机器也可以通过 ssh 访问 这个电脑 但是有…...

kkFileView报错no office manager available

背景 部署环境:虚机Linux系统 发生问题的版本:4.1.0-SNAPSHOT 现象:有的docx文件可以预览,有的不可以。不可以的就怎么打开都不可以(不管你是躺着,站着,坐着,睡着,趴着都不行,哈哈) 报错内容 贴出主要的报错内容步骤: > no office manager available > tr…...

ARMS 助力假面科技研发运维提效,保障极致游戏体验

客户介绍与项目背景 假面科技成立于 2014 年&#xff0c;致力于打造创新的数字产品&#xff0c;火爆一时的“狼人杀”、“谁是卧底”、“足记相机”都是假面科技旗下产品&#xff0c;公司产品总数超过 40 款&#xff0c;覆盖用户数超过 2 亿人。 随着业务的持续发展&#xff…...

趣味数学300题1981版-八个等式、五个5等于24

八个等式 分析&#xff1a;此问题的求解思路是按照最后一步运算的运算符号进行分类。示例中最后一步的运算是除法&#xff0c;只要被除数与除数相等且不为0&#xff0c;就可以得到结果1.因此我们还可以对于结果等于1的情况列出其他的算式。如果保持最后一步运算为除法运算&…...

关闭超时订单和七天自动确认收货+RabbitMQ规范

关闭超时订单 创建订单之后的一段时间内未完成支付而关闭订单的操作&#xff0c;该功能一般要求每笔订单的超时时间是一致的 TTL&#xff08;Time To Live&#xff09;存活时间&#xff0c;只能被设置为某个固定的值&#xff0c;不能更改&#xff0c;否则抛出异常 死信&#…...

DDD领域驱动开发第2讲:领域驱动开发在货代订单业务的实践

领域驱动开发在货代订单业务的实践 本文是DDD领域驱动开发第2讲,先讲解当前业务存在哪些问题,什么是DDD,为啥需要使用DDD解决现有业务问题,DDD让技术主动理解业务,通过领域模型将可以描述各个业务领域之间的关系,最后讲解领域驱动开发在货代订单的实践。 文章目录 领域驱…...

【Qt学习】| 如何使用QVariant存储自定义类型

QVariant是Qt框架中的一个通用数据类型&#xff0c;可以存储多种类型的数据&#xff0c;主要作用是提供一种类型安全的方式来存储和传递不同类型的数据&#xff0c;而不需要显示地指定数据类型。 QVariant提供了诸多构造函数可以非常方便地对基础数据类型&#xff08;如&#x…...

分割 学习笔记cvpr2024

目录 LiteMedSam 模型37m LightM-Unet 500 str 依赖项: MLWnet 73 star memsam 340M 126 star LiteMedSam 模型37m https://github.com/bowang-lab/MedSAM/blob/LiteMedSAM/README.md LightM-Unet 500 str https://github.com/MrBlankness/LightM-UNet/blob model = Li…...

【多模态处理篇一】【 深度解析DeepSeek图文匹配:CLIP模型迁移实战——从原理到落地的保姆级教程】

引言:当CLIP遇到DeepSeek,会发生什么化学反应? 如果说CLIP是OpenAI为多模态领域投下的"原子弹",那DeepSeek的迁移实战方案就是给这颗原子弹装上了精确制导系统。这个组合能让你用一张猫咪表情包搜到全网同类梗图,还能让电商平台自动生成百万级商品描述,甚至帮…...