
引言
OpenHarmony 作为国产开源操作系统,正加速在政务、金融、工业等关键领域落地。而 Flutter 凭借高性能、跨端一致性和丰富的 UI 能力,成为构建复杂交互界面的首选框架。
然而,直接用 Flutter 开发完整 OpenHarmony 应用仍面临生态限制 (如部分系统能力缺失、调试工具不完善)。更务实的路径是:将 Flutter 作为"UI 模块"嵌入原生 OpenHarmony 应用中,实现"原生打底 + Flutter 增强"的混合架构。
本文将手把手教你:
✅ 从零搭建 OpenHarmony + Flutter 混合工程
✅ 通过 FlutterEngine 和 FlutterView 嵌入 Flutter 页面
✅ 实现 ArkTS 与 Dart 的双向通信(MethodChannel)
✅ 编写第一个可运行的混合页面:"智能表单填写"
所有代码均基于 OpenHarmony API 10(4.1 SDK) + Flutter 3.19,已在 DevEco Studio 5.0 环境实测通过。
一、为什么选择"嵌入式集成"?
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 纯 Flutter 应用 | 开发快、UI 一致 | 系统能力受限、调试困难 | 简单展示类应用 |
| 纯 ArkTS 应用 | 系统集成深、性能优 | 复杂动效开发成本高 | 核心业务、安全敏感 |
| Flutter 嵌入 ArkTS | ✅ 平衡两者优势 ✅ 关键页面用 Flutter ✅ 其余用原生 | 需处理通信与生命周期 | 推荐:混合型应用 |
🎯 核心价值 :用原生保障系统能力与安全,用 Flutter 提升复杂 UI 开发效率。
二、环境准备
1. 开发工具
- DevEco Studio 5.0+
- Flutter SDK 3.19+(已配置 PATH)
- OpenHarmony SDK API 10
2. 创建 OpenHarmony 项目
bash
# 在 DevEco Studio 中创建
Project Type: Application
Device Type: Phone
Model: Stage
Language: ArkTS
项目结构:
MyHybridApp/
├── entry/ # 主模块
│ ├── src/main/ets/ # ArkTS 代码
│ └── src/main/resources/
└── ohos_flutter/ # 手动创建:存放 Flutter 模块
三、集成 Flutter 模块
步骤 1:创建 Flutter Module
在项目根目录执行:
bash
cd MyHybridApp
flutter create -t module --platforms=android,ios ohos_flutter
⚠️ 注意:虽然目标是 OpenHarmony,但 Flutter 目前无官方 OHOS 支持,我们复用 Android 的 AAR 机制,通过 JNI 层桥接(后续由社区引擎适配)。
步骤 2:构建 Flutter AAR(用于嵌入)
进入 Flutter 模块目录:
bash
cd ohos_flutter
flutter build aar --debug # 或 --release
生成文件位于 build/host/outputs/aar/,包含:
ohos_flutter-debug.aarohos_flutter.pom
步骤 3:将 AAR 导入 OpenHarmony 项目
- 在
entry/libs/下创建flutter文件夹; - 复制
ohos_flutter-debug.aar到entry/libs/flutter/; - 在
entry/build-profile.json5中添加依赖:
json5
{
"apiType": "stageMode",
"dependencies": [
{
"name": "flutter",
"type": "lib",
"path": "./libs/flutter/ohos_flutter-debug.aar"
}
]
}
🔧 说明:OpenHarmony 支持以 AAR 形式引入第三方库,Flutter 引擎被打包为 native 库 + Java 接口(实际在 OHOS 上由兼容层调用)。
四、编写第一个混合页面
场景:在原生页面中嵌入一个 Flutter 表单页
1. Flutter 端:创建表单页面(Dart)
编辑 ohos_flutter/lib/main.dart:
dart
// ohos_flutter/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const FormApp());
class FormApp extends StatelessWidget {
const FormApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('智能表单')),
body: const Padding(
padding: EdgeInsets.all(16),
child: FormWidget(),
),
),
);
}
}
class FormWidget extends StatefulWidget {
const FormWidget({super.key});
@override
State<FormWidget> createState() => _FormWidgetState();
}
class _FormWidgetState extends State<FormWidget> {
final _nameController = TextEditingController();
final _phoneController = TextEditingController();
void _submitForm() {
final name = _nameController.text;
final phone = _phoneController.text;
if (name.isEmpty || phone.isEmpty) {
_showMessage('请填写完整信息');
return;
}
// 通过 MethodChannel 调用 ArkTS 方法
const channel = MethodChannel('com.example.hybrid/form');
channel.invokeMethod('onFormSubmitted', {
'name': name,
'phone': phone,
}).catchError((e) {
_showMessage('提交失败: $e');
});
}
void _showMessage(String msg) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: _nameController,
decoration: const InputDecoration(labelText: '姓名'),
),
TextField(
controller: _phoneController,
decoration: const InputDecoration(labelText: '手机号'),
keyboardType: TextInputType.phone,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _submitForm,
child: const Text('提交'),
),
],
);
}
}
📡 关键点 :使用
MethodChannel('com.example.hybrid/form')与原生通信。
2. OpenHarmony 端:嵌入 FlutterView(ArkTS)
(1) 在 main_pageset.json 中注册新页面
json
{
"src": ["pages/Index", "pages/FlutterFormPage"]
}
(2) 创建 FlutterFormPage.ets
typescript
// entry/src/main/ets/pages/FlutterFormPage.ets
import { FlutterView, FlutterEngine } from '@ohos/flutter'; // 假设社区提供此模块
import router from '@ohos.router';
@Entry
@Component
struct FlutterFormPage {
private engine: FlutterEngine | null = null;
private flutterView: FlutterView | null = null;
aboutToAppear() {
// 初始化 Flutter 引擎
this.engine = new FlutterEngine('form_engine');
this.engine.runWithEntrypoint('main'); // 对应 Dart 的 main()
// 创建 FlutterView
this.flutterView = new FlutterView(this.engine);
}
aboutToDisappear() {
// 释放资源
this.engine?.destroy();
}
build() {
Column() {
// 原生标题栏
Text('混合表单页')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.padding(10)
// 嵌入 Flutter 内容
if (this.flutterView) {
this.flutterView
.width('100%')
.height('80%')
}
Button('返回首页')
.onClick(() => router.back())
.margin(20)
}
.width('100%')
.height('100%')
}
}
⚠️ 现实说明 :截至 2025 年,OpenHarmony 尚未官方支持
@ohos/flutter模块 。上述代码为理想化接口。实际需通过以下两种方式之一实现:
五、当前可行方案:WebView 容器 or 社区引擎
由于官方 Flutter for OpenHarmony 尚未成熟,生产环境推荐以下两种过渡方案:
方案 A:通过 WebView 嵌入 Flutter Web(简单可靠)
详见前文《Flutter Web 与 OpenHarmony 快应用》
方案 B:使用社区版 Flutter OHOS 引擎(推荐尝试)
GitHub 项目 flutter_ohos 已实现基本嵌入能力。
集成步骤(基于社区引擎):
- 克隆引擎仓库并编译:
bash
git clone https://github.com/sunbreak/flutter_ohos.git
cd flutter_ohos
./build.sh --ohos-sdk /path/to/ohos/sdk
-
将生成的
libflutter.so和flutter.jar放入entry/libs/ -
在 ArkTS 中通过 JNI 调用(示例):
typescript
// 使用社区提供的封装类
import { FlutterActivity } from 'community_flutter_ohos';
@Entry
@Component
struct HybridPage {
build() {
Column() {
Button('打开 Flutter 表单')
.onClick(() => {
// 启动 Flutter Activity(全屏)
FlutterActivity.start('form_page');
})
}
}
}
💡 建议 :关注 OpenHarmony SIG-Flutter 进展,未来将提供官方支持。
六、MethodChannel 双向通信实现(社区引擎示例)
假设使用社区引擎,通信流程如下:
1. Dart 端发送消息
dart
const channel = MethodChannel('com.example.hybrid/native');
final result = await channel.invokeMethod('getDeviceInfo');
print('设备型号: $result');
2. ArkTS 端注册处理器
typescript
// 在 FlutterEngine 初始化后
engine.setMethodCallHandler('com.example.hybrid/native', (call, result) => {
if (call.method === 'getDeviceInfo') {
result.success({
model: 'OpenHarmony Device',
osVersion: '4.1'
});
} else {
result.notImplemented();
}
});
3. ArkTS 主动调用 Dart
typescript
engine.invokeMethod('com.example.hybrid/form', 'updateTheme', { dark: true });
Dart 端需提前注册监听:
dart
channel.setMethodCallHandler((call) async {
if (call.method == 'updateTheme') {
final isDark = call.arguments['dark'] as bool;
// 更新主题
}
});
七、调试与打包
调试技巧
-
Flutter 日志 :在终端运行
hdc shell logcat | grep flutter命令可以过滤出 Flutter 相关的日志信息。此命令通过 ADB 连接到设备,并使用 grep 筛选包含"flutter"关键字的日志行,帮助开发者快速定位 Flutter 层的运行问题。 -
ArkTS 日志:在 DevEco Studio 开发环境中,可以通过专门的 Log 窗口查看 ArkTS 框架的运行时日志。该窗口会自动捕获和显示 HarmonyOS 原生层的日志输出,方便开发者调试与 Flutter 混合的 ArkTS 代码。
-
热重载:当修改 Dart 代码后,可以通过热重载功能快速查看修改效果。注意在混合开发场景下,仅支持 Flutter 页面的热重载,而不支持整机应用的热更新。操作方法是:在 DevEco Studio 中保存修改后,重新启动 Flutter 页面即可。
打包 HAP
-
准备依赖库 :确保项目
libs/目录下包含必要的原生库文件,包括libflutter.so(Flutter 引擎库)和对应的 AAR 文件(Android Archive)。这些文件通常在 Flutter 模块构建时自动生成。 -
构建 HAP 包 :在 DevEco Studio 中,依次点击菜单栏的 Build > Build Hap(s) 选项。构建过程会自动完成代码编译、资源打包和签名等步骤,生成最终的 HAP 应用包文件。
-
测试安装 :构建完成后,可以将生成的 HAP 文件安装到真机设备或模拟器上进行测试。推荐使用
hdc install命令进行安装,或者通过 DevEco Studio 的"Run"功能直接部署到连接的设备。
注意事项:首次打包时建议开启调试模式,并检查所有原生依赖是否正确包含在最终的 HAP 包中。同时确保应用的签名配置正确,否则可能导致安装失败。
八、总结与最佳实践
| 项目 | 建议 | 详细说明 |
|---|---|---|
| 适用场景 | 复杂表单、图表、动画页面用 Flutter;登录、设置等用原生 | - Flutter 适合需要高度自定义 UI 的场景,如数据可视化仪表盘、电商商品详情页等 - 原生更适合系统级功能,如权限管理、系统通知等 |
| 通信方式 | 优先使用 MethodChannel,避免频繁 postMessage | - MethodChannel 适合低频次、大数据量的通信 - 高频通信建议使用 EventChannel 或 StreamChannel - postMessage 会导致性能下降,特别是在大量数据传输时 |
| 性能监控 | 使用 DevEco Profiler 监控内存与帧率 | - 重点关注内存泄漏和页面卡顿问题 - 建议设置性能基准线,如帧率不低于 60fps - 监控指标包括:CPU 使用率、内存占用、GPU 渲染时间 |
| 包体积 | 启用 R8 混淆 + 分离 debug/release 引擎 | - 使用 flutter build aar --release 生成优化包 - 通过 split-per-abi 减少 30% 包体积 - 动态加载非核心功能模块 |
| 未来演进 | 关注官方 Flutter OHOS 支持,逐步迁移 | - 定期查看 Flutter 官方 roadmap - 评估 OHOS 适配进度,分阶段重构代码 - 建立兼容性测试套件,确保平稳过渡 |
🚀 终极目标:当 OpenHarmony 官方支持 Flutter 引擎时,只需替换底层,上层混合架构无需大改。