
Dart 与鸿蒙(HarmonyOS)的交互主要通过 Platform Channel(平台通道) 实现,这是 Flutter 官方提供的跨平台通信机制。在 Flutter 鸿蒙化项目中,这种交互方式得到了完整的支持,使得 Dart 代码能够调用鸿蒙原生的能力。
Flutter 提供了三种基础通道类型来实现与鸿蒙原生的通信:
MethodChannel 是最主要的交互方式,适用于调用原生方法并接收返回值的场景。这种方式适合一次性调用,比如获取设备信息、网络状态等。在 Flutter 端,开发者创建一个 MethodChannel 实例,通过 invokeMethod 方法调用鸿蒙端实现的方法,并使用 await 等待返回结果。
EventChannel 用于事件流或数据流的持续通信,特别适合需要持续监听数据的场景,比如传感器数据订阅、电池电量变化监听等。这种方式是单向的,鸿蒙端可以持续向 Flutter 端推送数据。
BasicMessageChannel 适合传递字符串或二进制信息的双向通信场景,支持快速连续传递简单数据。与 MethodChannel 不同的是,它提供了更灵活的通信模式,可以实现双向的数据交换。
在 Flutter 端,交互流程遵循以下模式:首先创建通道实例,定义唯一的通道名称用于标识通信路径;然后通过 invokeMethod 发起调用,传入方法名和参数;最后使用 async/await 模式接收返回结果或处理错误。
在鸿蒙端(ArkTS),需要继承 FlutterPlugin 类实现 onAttachedToEngine 方法,在该方法中创建与 Flutter 端同名的通道实例。同时需要实现具体的处理逻辑,包括方法调用的处理、错误返回以及结果回传等。
关于 Dart 和鸿蒙是否在同一个线程的问题,答案是它们运行在不同的线程体系中,但通过精心设计的通信机制实现了高效的跨线程协作。
Flutter 使用多个线程来完成其必要的工作。UI 线程是 Dart 代码的执行环境,运行 Dart VM 中的所有 Dart 代码,包括开发者编写的业务逻辑和 Flutter 框架生成的代码。当应用创建和展示场景时,UI 线程首先建立一个图层树(layer tree),包含设备无关的渲染命令,然后将其发送到 GPU 线程进行渲染。
Raster 线程(光栅化线程,又称 GPU 线程)负责将 layer tree 交给 GPU 进行渲染。图形库 Skia 在该线程运行。I/O 线程执行高负载的操作以避免阻塞 UI 或 Raster 线程,常见于文件读写、网络请求等场景。平台线程是鸿蒙的主线程,插件代码在这里运行。
鸿蒙系统中,应用以任何形式启动时系统为其创建进程,每个进程都会有一个主线程(UI 线程)。主线程负责 UI 绘制、管理 ArkTS 引擎实例、分发交互事件、处理应用代码回调等核心工作。
除主线程外,鸿蒙还提供了 Worker 线程用于执行耗时操作,但 Worker 线程不能直接操作 UI。系统提供了多种任务分发器,包括 GlobalTaskDispatcher(全局任务分发器)、ParallelTaskDispatcher(并发任务分发器)、SerialTaskDispatcher(串行任务分发器)和 SpecTaskDispatcher(特定任务分发器)。
Dart 与鸿蒙的交互本质上是跨线程/跨进程的通信。Flutter 的 UI 线程通过消息传递与鸿蒙平台线程进行交互,而非直接在同一个线程中执行。当 Flutter 调用鸿蒙原生方法时,请求会被发送到平台线程处理,处理结果再通过消息队列返回给 Flutter 端。
这种设计确保了 Flutter UI 线程不会被阻塞,鸿蒙端的耗时操作可以在独立线程中执行,两者通过异步消息机制实现高效的协作。
Flutter 能够适配鸿蒙系统的核心原因在于其架构设计的灵活性和底层引擎的可移植性。
Flutter Engine 是 Flutter 的核心渲染引擎,它允许开发者将 Flutter 嵌入到非 Flutter 环境中。鸿蒙通过集成 Flutter Engine 来支持 Flutter 应用,这意味着开发者可以创建原生的鸿蒙应用程序,并在其中嵌入 Flutter 组件。
目前,OpenHarmony SIG 组织在 Gitee 上开源了兼容 OpenHarmony 的 Flutter 版本,包括 flutter_engine 和 flutter_flutter 项目。这些项目基于官方 Flutter 稳定版本进行适配,支持 Linux、Mac、Windows 环境下的开发。
鸿蒙官方已经提供对 Flutter 的支持,并且已适配 API 11 beta1。华为提供了完整的鸿蒙 Flutter 开发套件,包括环境配置、构建工具和调试支持。开发者可以使用 Flutter Tools 指令编译和构建鸿蒙应用程序,实现"终端一体化"的开发体验。
在渲染层面,Flutter 鸿蒙化工程采用了特殊的渲染管线设计。RenderService 线程(RS 线程)是 RenderService 进程的主线程,Flutter 渲染帧完成后,RS 线程进行合成并送显。在 Texture 模式下,Flutter 渲染后的 buffer 与应用的主线程合成后统一送显,受应用主线程的影响;在 Surface 模式下,Flutter 渲染帧单独送显。
Dart 的异步机制和鸿蒙 ArkTS 的 Promise 在设计理念上有诸多相似之处,但也存在显著差异。
Dart 使用 Future 表示异步操作的结果,鸿蒙 ArkTS 使用 Promise 处理异步操作。两者都支持三种状态:pending(进行中)、fulfilled(已完成)、rejected(已拒绝)。Dart 的 Future 就相当于 JavaScript 中的 Promise,用法也非常相似。
状态管理机制方面,两者都提供了状态机制来管理异步操作的不同阶段。Dart 通过 .then()、.catchError()、.whenComplete() 等方法处理异步结果;鸿蒙通过 .then()、.catch() 方法实现类似功能。
两者都提供了 async/await 语法糖来简化异步编程。在 Dart 中,async 函数返回 Future 对象,await 表达式等待 Future 完成;在鸿蒙中,async 函数返回 Promise 对象,await 等待 Promise 解析。
Dart 的异步编程示例:
Future<void> fetchData() async {
await Future.delayed(Duration(seconds: 2));
print('数据获取成功');
}鸿蒙的异步编程示例:
async function myAsyncFunction() {
const result = await new Promise((resolve) => {
setTimeout(resolve('Hello, world!'), 3000);
});
console.info(String(result));
}尽管语法相似,底层实现机制有显著区别。Dart 是单线程模型,通过事件循环(Event Loop)和微任务队列(Microtask Queue)实现异步。Dart 的异步不会创建新线程,而是将异步任务挂起,在事件循环中按顺序执行。
鸿蒙的 Promise 是基于 JavaScript 标准的异步实现,同样使用事件循环机制。但鸿蒙还提供了 TaskPool 和 Worker 线程机制用于真正的多线程并发执行。
Dart 提供了 Isolate 作为并发机制,这是类似于线程但不共享内存的独立运行单位。每个 Isolate 都有独立的事件循环和内存堆,通过消息传递进行通信。这种设计避免了多线程的共享内存问题,但通信开销相对较高。
鸿蒙提供了 TaskDispatcher 分发任务和 Emitter 进行线程间事件同步。TaskDispatcher 隐藏了任务所在线程的实现细节,支持指定任务优先级(HIGH、DEFAULT、LOW)。
当鸿蒙端返回 Promise 结果时,Flutter 端有多种方式接收这些返回值。
MethodChannel 是最常用的接收方式。Flutter 端调用 invokeMethod 方法后,会返回一个 Future 对象,开发者可以使用 await 或 .then() 接收结果:
final _platform = const MethodChannel('samples.flutter.dev/battery');
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final result = await _platform.invokeMethod<int>('getBatteryLevel');
batteryLevel = '获取等级 $result %';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
message = batteryLevel;
});
}在鸿蒙端,对应的方法实现需要返回 Promise:
async getBatteryLevel(): Promise<number> {
// 返回电池电量
return batteryLevel;
}两种方式都可以进行完善的错误处理。Flutter 端通过 on PlatformException 捕获平台异常;鸿蒙端通过 Promise 的 reject 或抛出异常来返回错误信息。这种设计确保了跨平台通信的健壮性,开发者可以统一处理正常流程和异常情况。
对于需要多次交互的场景,可以使用 BasicMessageChannel 实现双向通信。Flutter 端发送消息并等待回复,鸿蒙端接收消息、处理后返回结果:
final _basicChannel = const BasicMessageChannel(
"flutter.ohos.example/base_test",
StandardMessageCodec()
);
final String? reply = await _basicChannel.send('increment');这种方式适用于需要连续数据交换或快速多次通信的场景。
对于复杂的异步处理流程,可以利用 Dart Future 的链式调用特性:
_platform.invokeMethod<List<String>>('getData')
.then((data) => processData(data))
.then((processed) => formatResult(processed))
.catchError((error) => handleError(error))
.whenComplete(() => cleanup());这种方式保持了代码的可读性,同时支持复杂的异步操作组合。
Dart 与鸿蒙的交互通过 Platform Channel 实现,运行在不同但协作良好的线程体系中。Flutter 适配鸿蒙的核心在于其引擎的可移植性和鸿蒙官方的积极支持。两者的异步机制(Dart Future 与鸿蒙 Promise)在设计理念上高度相似,都支持 async/await 语法糖,但底层实现各有特点。Promise 返回值通过 MethodChannel 的 Future 机制传递,Flutter 可以使用 async/await 或链式调用接收和处理这些结果。
这种跨平台交互机制的设计,使得开发者能够用一套 Dart 代码库同时开发 Flutter 和鸿蒙原生功能,大大提升了开发效率和代码复用率。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net