欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

在这里插入图片描述

前言

Flutter 最让人爱不释手的特性之一就是 Hot Reload (热重载)。修改 UI 代码,保存,界面瞬间刷新,状态还能保留。

但是,如果你正在开发一个 纯 Dart 控制台应用(比如 CLI 工具、后端服务、或者跑在服务器上的爬虫脚本),默认情况下你是没有热重载的。每次改一行代码,都要 Ctrl+C 停止,然后重新 dart run,这简直是折磨。

hotreloader 库通过监听文件系统变化并利用 Dart VM Service 的重载能力,为你的 Dart 控制台应用带来了类似 Flutter 的热重载体验。

对于 OpenHarmony 开发者,这在开发一些运行在设备上的 后台服务(Service Ability)辅助脚本 时非常有用。

一、核心原理

Dart VM (虚拟机) 本身就支持热重载代码。Flutter 只是利用了这个能力。
hotreloader 做了两件事:

  1. Wather: 监听项目目录下 .dart 文件的修改事件。
  2. Reloader: 当检测到变化时,连接到本地 Dart VM Service (ws://localhost:xxxx),发送 reloadSources 指令。

保存文件

监听事件

请求重载

重载 Isolate

输出

开发者

FileSystem

HotReloader

Dart VM 服务

运行中的 Dart 程序

Console

二、集成与用法详解

2.1 添加依赖

通常作为 dev_dependencies 或正常依赖。

dependencies:
  hotreloader: ^4.3.0

2.2 启用热重载

只需要在你的 main 函数开头加一行代码。

import 'dart:async';
import 'package:hotreloader/hotreloader.dart';

Future<void> main(List<String> args) async {
  // 1. 初始化热重载器
  // 它会自动寻找 vm-service 并连接
  await HotReloader.create(
    onAfterReload: (ctx) => print('🔥 热重载完成!'),
  );

  // 2. 你的业务逻辑
  print('应用已启动,等待代码变更...');
  
  // 模拟一个长运行的任务
  Timer.periodic(Duration(seconds: 2), (timer) {
    print('当前时间: ${DateTime.now()}');
    // 你可以在运行过程中修改这一行代码,观察输出变化
  });
}

在这里插入图片描述

2.3 运行方式的关键

要让热重载生效,必须在启动时开启 VM Service

# 必须带上 --enable-vm-service 参数
dart run --enable-vm-service bin/main.dart

如果是编译后的 AOT 程序(dart compile exe),不支持热重载。

三、OpenHarmony 适配与实战

3.1 鸿蒙上的 Dart 脚本开发

在鸿蒙设备上开发 Dart 脚本时,比如一个本地的 HTTP Server 或日志监控脚本,我们可以利用 hotreloader 加速调试。

注意:鸿蒙系统对端口和权限有严格限制。

  1. 网络权限:需要在 module.json5 中申请 ohos.permission.INTERNET,因为 VM Service 是通过 WebSocket 通信的。
  2. 端口监听:确保 VM Service 监听的端口未被占用。

在这里插入图片描述

3.2 远程热重载 (Remote Hot Reload)

如果你在 PC 上开发,代码同步推送到鸿蒙设备上运行。你可以在鸿蒙设备上启动 Dart VM,并暴露 Service 端口。
然后配置 hotreloader 去连接远程 IP。

// 高级用法:连接指定地址
await HotReloader.create(
    // 虽然 hotreloader 库本身主要用于本地 loopback
    // 但原理上只需要 VM Service URL
);

不过通常来说,hotreloader 更多用于 开发 PC 端工具 用来辅助鸿蒙开发(例如:编写一个自动生成鸿蒙资源的脚本)。

四、注意事项

4.1 状态保持

与 Flutter 的 Hot Reload 一样,hotreloader 尝试保留状态。

  • 全局变量:会被保留。
  • 正在执行的函数:旧代码会继续执行直到结束,下一次调用才会使用新代码。
  • Timer:像上面的例子,Timer 的回调闭包如果定义在 main 内部,可能需要特殊处理才能让它更新逻辑。最佳实践是将逻辑提取到全局函数或顶层类方法中
// 不推荐:闭包难以热重载
Timer.periodic(..., (t) { ... }); 

// 推荐:提取函数
void myTask(Timer t) {
  print('逻辑 v1');
}

void main() {
   // ... init reloader
   Timer.periodic(Duration(seconds: 1), myTask);
}

当你修改 myTask 的内容保存后,下一次 Timer 触发时就会执行新逻辑。

五、总结

hotreloader 补全了 Dart 生态中“非 Flutter 应用”的开发体验短板。

对于 OpenHarmony 开发者:

  • 如果你正在用 Dart 编写 CLI 工具(如构建脚本、资源处理工具),它是必装神器。
  • 如果你在写 Dart 后端服务(Dart Frog 等),它通常已经内置或可以通过此库集成。

它让 Dart 变成了一个真正的“脚本语言”般的开发体验,修改即生效,无需反复编译重启。

最佳实践

  1. 只在开发环境使用:通过 const bool.fromEnvironment('dart.vm.product') 判断,在生产环境跳过初始化。
  2. 合理拆分代码:将长驻逻辑拆分为独立函数,确保热重载能生效。
  3. 注意资源释放:如果在热重载钩子 (onBeforeReload) 中需要释放文件句柄或数据库连接,请务必处理,防止资源泄漏。

六、完整实战示例

import 'dart:io';
import 'dart:async';
import 'package:hotreloader/hotreloader.dart';

// 假设这是一个长时间运行的后台服务(如 Mock Server 或 构建脚本)
void main() async {
  // 1. 初始化热重载监听器
  // 它会监听当前项目 *.dart 文件的变化
  await HotReloader.create(
    onAfterReload: (ctx) {
      print('🔥 热重载完成!代码已更新,无需重启服务。');
    },
  );

  print('🚀 服务启动,PID: ${pid}。修改代码并保存看看效果...');
  
  // 2. 启动周期性任务
  // 关键点:将业务逻辑提取为顶层函数 `tick`
  Timer.periodic(Duration(seconds: 2), tick);
}

// 尝试修改这个函数中的打印内容并保存文件
// 例如把 "逻辑 v1" 改为 "逻辑 v2"
void tick(Timer t) {
  print('Tick: ${DateTime.now().toIso8601String()} - 正在执行逻辑 v1');
}
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐