fluter在混合模式便捷的热加载

145 阅读3分钟

1. 前言

flutter应用有两种调试环境:

  • 纯flutter工程:整个app被flutter接管
  • flutter混合模式开发,也称之为add-to-app模式。flutter作为sdk集成到App中。

这里要讲的是混合模式下的调试

2. add-to-app模式调试

flutter开发效率高其中一个原因是代码的hot reload。flutter在debug模式下会开启hot reload,代码为JIT。

纯flutter工程通过命令 flutter run命令启动app,天然支持热加载。但在混合模式下如何实现热加载呢?

有两种办法:

  1. app启动后,用命令flutter attach
  2. 使用VSCode插件

对比两者,我个人感觉VSCode插件比较方便,为什么?因为当修改代码后,第一种方法需要在命令行按下r才可以实现hot reload,而vscode插件可以实现自动hot reload,不需要额外的步骤。

2.1. flutter attach

➜  my_flutter git:(main) ✗ flutter attach
Connected devices:
iPhone13 Pro (mobile) • 00008110-000925E02146401E            • ios • iOS 18.5 22F76
iPhone 16 (mobile)    • 0F117065-677D-4941-B66B-99EDC4B99B0A • ios • com.apple.CoreSimulator.SimRuntime.iOS-18-5 (simulator)

No wireless devices were found.

[1]: iPhone13 Pro (00008110-000925E02146401E)
[2]: iPhone 16 (0F117065-677D-4941-B66B-99EDC4B99B0A)
Please choose one (or "q" to quit): 1
Waiting for a connection from Flutter on iPhone13 Pro...
Syncing files to device iPhone13 Pro...                             6.5s

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
c Clear the screen
q Quit (terminate the application on the device).

2.2. VSCode插件

  1. 安装flutter插件:官方文档。比我讲的清楚。
  2. debug模式启动add-to-app。
  3. 在vscode工程中按下command+shift+p:选择Flutter:Select Device,选择你的设备
  4. 在vscode工程中按下command+shift+p:选择Debug:Attach to Flutter on Device,选择你的设备
  5. 查看vscode提示,等待链接成功
  6. 修改代码实现hot reload

3. 如何实现脱机(离开xcode环境)调试

3.1. 结论

不能实现

3.2. 为什么不能实现?

  1. Debug 模式使用的是 动态加载的 Dart 代码(JIT)
  2. Flutter 引擎在启动时默认会从开发机上的 Dart VM 服务端口加载 main.dart 编译后的代码(kernel_blob.bin 等);
  3. 脱机环境(非 flutter run 启动或非 Xcode 启动)下,App 本身没有包含这些文件;
  4. 所以在脱离 Flutter CLI 或 Xcode 的 debug 会话后启动,会找不到 Flutter 的入口代码。

4. debug包提测

4.1. 问题:

  • 有些业务需要再debug模式下提测,但提交给测试工程师的debug包flutter初始化会失败。

4.2. 原因:

4.2.1. 分析

  • Debug 模式的 Flutter Add-to-App 项目中,flutter module 会被编译为debug包。FlutterEngine 启动时会尝试 连接开发主机上的 flutter attach 服务,用于:
    • 调试功能(热重载、日志打印、DevTools)
    • 加载 Dart VM snapshot 等临时调试资源
  • 而这些功能只有在 Xcode 启动时会设置好相关参数路径(通过环境变量或启动参数传入)

4.2.2. 所以:

  • ✅ Xcode 启动时,会自动设置 --observatory-port 等参数,FlutterEngine 知道去哪找 Dart runtime
  • ❌ 图标点击启动时,这些参数没有传入,FlutterEngine 找不到调试环境、资源路径,导致 run 返回 NO(Dart isolate 无法启动)

4.3. 如何解决

  • 思路:在debug App包中中使用flutter module的profile或release包。profile或release包不依赖xcode提供的环境。但也不能hot reload dart代码。
  • 实现:可以通过设置上面提到的“environment['FLUTTER_BUILD_MODE']”环境变量,控制flutter module的编译模式
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/yidao/Documents/env/1/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/yidao/Documents/code/flutter/my_flutter"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

# debug profile release
export "FLUTTER_BUILD_MODE=release"