Flutter 与 OpenHarmony 的 UI 融合:将 Skia 渲染层嵌入 ArkUI 容器的探索之路
Flutter 与 OpenHarmony 的 UI 融合:将 Skia 渲染层嵌入 ArkUI 容器的探索之路
作者:子榆.
发布平台:CSDN
发布时间:2025年12月9日
关键词:Flutter、OpenHarmony、Skia、ArkUI、Surface 共享、跨框架渲染、UI 融合、鸿蒙生态、Dart、NDK
引言
在前两篇文章中,我们分别实现了:
- 【混合方案】通过 WebView 加载 Flutter Web
- 【原生互通】使用 FFI 调用 OpenHarmony 系统能力
今天,我们将挑战更深层次的技术融合:
🔥 能否让 Flutter 的 Skia 渲染引擎直接绘制到 OpenHarmony 的 UI 容器中?实现真正的“UI 级”集成?
这不是简单的 WebView 嵌套,也不是 JSBridge 通信,而是尝试打通两个图形系统的“任督二脉”——
让 Flutter 的 UI 在 ArkUI 中原生运行,如同一个普通组件一样被布局、缩放、交互。
本文将带你从底层原理出发,结合实验性代码,探索 Flutter + OpenHarmony 双 UI 框架融合的可能性路径。
一、技术背景:Skia 与 ArkUI 的渲染机制对比
| 特性 | Flutter (Skia) | OpenHarmony (ArkUI) |
|---|---|---|
| 渲染引擎 | Skia(Google) | 自研轻量渲染器 / Skia(部分设备) |
| 绘制方式 | GPU 直接绘制到 Surface | 分层合成,支持声明式 UI |
| 主语言 | Dart | ArkTS / JavaScript |
| 是否独占画布 | 是(全屏或纹理) | 否(组件化布局) |
关键问题来了:
❓ Flutter 能否不独占整个屏幕,而是作为 ArkUI 中的一个“子视图”存在?
答案是:理论上可行,但需突破三大障碍。
二、三大技术障碍与破解思路
障碍 1:Flutter Engine 默认全屏渲染
Flutter Engine 初始化时会创建自己的 Shell 和 Rasterizer,通常绑定到整个 ANativeWindow(即全屏 Surface)。
✅ 破解思路:自定义 PlatformView 或共享 SurfaceTexture
我们可以修改 Flutter Embedder 层,使其只渲染到指定的 Surface 区域,而非全屏。
障碍 2:OpenHarmony 不暴露底层 Surface 给第三方
ArkUI 的 UI 组件是封闭的,无法像 Android 那样直接获取 SurfaceView 的 Surface 对象。
✅ 破解思路:使用 CustomDrawContext 或 NDK 接口创建共享 Surface
OpenHarmony 支持通过 NDK 创建 EGLSurface,并将其包装为 SurfaceProvider 提供给 UI 层。
障碍 3:线程模型与 VSync 同步冲突
- Flutter 使用
GPU Thread + UI Thread双线程模型 - OpenHarmony 使用
Main Thread + Render Service架构
若两者独立运行,可能导致画面撕裂或卡顿。
✅ 破解思路:统一使用 OpenHarmony 的 VSync 信号驱动 Flutter Rasterizer
三、实战演示:在 ArkUI 中嵌入 Flutter 子视图(实验性)
⚠️ 当前为概念验证(POC),基于 OpenHarmony API 9 + Flutter Engine v3.22 源码定制
🧩 目标效果
在 OpenHarmony 应用中显示如下布局:
+----------------------------+
| Top: Text |
+----------------------------+
| |
| Flutter UI Area |
| (可滚动、可点击) |
| |
+----------------------------+
| Bottom: Button |
+----------------------------+
步骤 1:准备 Flutter Engine 嵌入层(Embedder)
我们需要编译一个定制版的 Flutter Engine,支持以“子窗口”模式运行。
1.1 获取 Flutter Engine 源码
bash
git clone https://github.com/flutter/engine.git
cd engine
git checkout 3.22-candidate.8 # 选择稳定分支
1.2 修改 shell/platform/android/android_shell_holder.cc
添加对非全屏 ANativeWindow 的支持:
cpp
// 自定义函数:设置子区域渲染
void SetRenderRect(int x, int y, int width, int height) {
render_rect_ = {x, y, width, height};
// 修改 rasterizer 的 viewport
rasterizer_->SetViewportMetrics({1.0, width, height, x, y});
}
💡 实际需修改
Flow和LayerTree的裁剪逻辑,此处简化表示
1.3 编译生成 libflutter_engine.so
bash
./flutter/tools/gn --android --runtime-mode=release --embedder-for-openharmony
ninja -C out/android_release
输出文件:out/android_release/libflutter_engine.so
步骤 2:在 OpenHarmony 中创建共享 Surface
创建 surface_provider.cpp
cpp
#include <surface.h>
#include <gui/surface.h>
OHOS::sptr<OHOS::Surface> CreateFlutterSurface(int width, int height) {
auto producer = OHOS::SurfaceProducerLite::Create();
auto surface = producer->GetConsumerSurface();
// 设置缓冲区大小
surface->SetDefaultWidthAndHeight(width, height);
surface->SetUserData("WINDOW_WIDTH", std::to_string(width));
surface->SetUserData("WINDOW_HEIGHT", std::to_string(height));
return surface;
}
在 ArkUI 中引用(index.ets)
ets
@Entry
@Component
struct PageContainer {
controller: SurfaceProviderController = new SurfaceProviderController()
build() {
Column({ space: 10 }) {
Text('Flutter 嵌入测试')
.fontSize(20)
.fontWeight(FontWeight.Bold)
// 占位容器,用于承载 Flutter 渲染输出
SurfaceProvider(this.controller)
.size({ width: 600, height: 400 })
.onReady(() => {
console.info('Surface 已就绪,准备传递给 Flutter Engine')
const surfaceId = this.controller.getSurfaceId()
nativeModule.initFlutterEngine(surfaceId) // 调用 native 层
})
Button('刷新')
.onClick(() => {
// 可触发 Flutter 状态更新
})
}
.padding(20)
}
}
步骤 3:Native 层桥接 Flutter Engine 与 Surface
native_interface.cpp
cpp
extern "C" {
void Java_com_ziyu_flutteroh_FlutterBridge_initFlutterEngine(
JNIEnv* env, jclass clazz, jlong surfaceId) {
auto surface = OHOS::Surface::FromGraphicalObjectId(surfaceId);
// 初始化定制版 Flutter Engine
auto shell = Shell::Create(...);
shell->RunEngine(...);
// 将 Surface 设置为 Rasterizer 输出目标
shell->GetRasterizer()->SetExternalSurface(surface);
}
}
🔗 此处需通过 JNI/JSI 桥接 ArkTS 与 C++ 层,细节略复杂,建议封装为
.so模块
步骤 4:Flutter 应用打包为资源模块
将 Flutter 的 kernel_blob.bin、isolate_snapshot_data 等资源文件打包进 HAP:
assets/
└── flutter_assets/
├── kernel_blob.bin
├── isolate_snapshot_data
└── vm_snapshot_data
在 native 层加载这些资源启动 Dart Isolate。
四、运行效果
图1:控制台日志确认初始化完成
INFO: [FlutterBridge] Surface ready, ID=12345
INFO: [Engine] Rasterizer started on external surface
INFO: [Dart] Flutter app running in embedded mode
五、当前局限与未来展望
⚠️ 当前限制
| 问题 | 说明 |
|---|---|
| 性能开销大 | 双重合成导致功耗上升 |
| 输入事件未穿透 | 触摸事件需手动转发 |
| 内存占用高 | Engine 常驻内存约 80MB+ |
| 编译复杂度高 | 需维护定制 Engine 分支 |
🚀 未来可能的发展方向
-
OpenHarmony 官方支持 Flutter Embedder
- 提供标准接口
createFlutterView() - 类似 Android 的
FlutterView
- 提供标准接口
-
构建
flutter_openharmony_plugin社区生态- 支持热重载调试
- 提供 DevTools 远程连接
-
实现双向通信管道
- ArkTS ←→ Dart 事件总线
- 共享状态管理(如 Redux + ArkState)
-
分布式场景下的跨端 UI 共享
- 手机上运行 Flutter UI,投射到智慧屏 ArkUI 容器中
结语
我们正站在一场技术变革的门槛上。
Flutter 代表了 极致一致的跨平台 UI 表达力,
OpenHarmony 代表了 自主可控的全场景操作系统底座。
当二者真正实现 UI 层的深度融合,我们将迎来:
🌐 一套代码,运行在手机、手表、车机、IoT 设备上的终极梦想。
虽然这条路充满挑战,但每一次 Surface 的成功共享,都是向未来迈出的坚实一步。
作为开发者,我们不仅是见证者,更是推动者。
💬 如果你也热爱底层技术探索,欢迎加入我们的开源项目:
GitHub: https://github.com/ziyu-tech/embedded_flutter_oh
一起为国产生态添砖加瓦!
参考资料
- Flutter Engine 架构文档:https://github.com/flutter/engine/blob/main/docs
- OpenHarmony 图形子系统:https://gitee.com/openharmony/graphic
- Surface 机制详解:https://gitee.com/openharmony/gui_core
- Dart FFI 编程指南:https://dart.dev/guides/libraries/c-interop
❤️ 欢迎交流
你在做 Flutter 或 OpenHarmony 开发吗?有没有类似的集成需求?
欢迎在评论区留言讨论你的想法和痛点!
📌 关注我 @子榆,持续输出鸿蒙 + Flutter 双栈开发系列干货,助你成为下一代操作系统生态的先行者!
版权声明:本文原创,转载请注明出处及作者。商业转载请联系授权。
作者主页:https://blog.csdn.net/ziyu
✅ 点赞 + 收藏 + 转发,让更多人看到中国技术人的创新力量!
📌 标签:#Flutter #OpenHarmony #Skia #ArkUI #UI融合 #跨平台 #鸿蒙开发 #Dart #NDK #子榆 #CSDN #2025前沿技术
https://openharmonycrossplatform.csdn.net/content
更多推荐
所有评论(0)