1. 项目概述:为什么要在开源鸿蒙上做Flutter AR应用
先交代一下背景。我最近在调研“开源鸿蒙+Flutter”这套技术组合在端侧交互类App上的落地可行性,顺手做了一个AR太空探索应用的Demo。这个Demo不算复杂,但刚好把开源鸿蒙的分布式能力、Flutter的跨平台渲染、AR的实时相机合成这三件事串在了一起,回过头来看,踩坑记录和方案取舍反而比Demo本身更有价值。
这个项目适合谁看?两类人。一类是想在开源鸿蒙设备上做应用、但对ArkUI还不熟、想用Flutter保住跨平台生产力的团队;另一类是对AR感兴趣、想找一个“不依赖大厂SDK也能跑通AR基础流程”的参考实现的人。如果你只是单纯想学Flutter Widget,这个项目对你来说偏底层;如果你是想了解“鸿蒙上能不能跑Flutter、跑起来效果如何”,那这篇内容基本覆盖了从环境到上手的完整链路。
我选“太空探索”这个题材,不是为了炫酷,而是AR场景里它天然具备三个优势:一来星空背景不需要高精地图或真实物理场景,规避了OpenHarmony上SLAM能力不成熟的短板;二来星球模型的渲染对传感器精度要求不高,主要靠陀螺仪和相机姿态估算,门槛低;三来太空题材在视觉上有天然的“沉浸感”,即便画面精度一般,用户也愿意接受。这个选题思路,我认为比技术本身更值得分享——AR落地的关键不是技术上限,而是场景和现实约束的匹配度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与工具链选型
2.1 开源鸿蒙版本与设备选型
先说结论:如果你也想复现这个流程,建议直接上OpenHarmony 4.0及以上版本,配套DevEco Studio 4.0 Release。低版本不是不能用,但API的变动会让人非常难受,尤其是权限模型和相机接口这块,3.x和4.x差别很大。
设备方面,我一开始用Dayu 200开发套件,后来换成了润和RK3568的板子。说实话,除非你要做多设备协同或者碰分布式软总线,否则用模拟器就够了。但注意,OpenHarmony的模拟器对Flutter的支持也不算好,x86镜像跑起来倒是不卡,但AR需要的相机能力在模拟器里基本是残废的。我做AR相关功能时全程用的真机,模拟器只用来验证UI布局。
有个细节值得提一下:OpenHarmony的设备类型很多,Pad、电视、开发板都有,它们的屏幕分辨率和传感器配置差异很大。如果你的AR应用要做姿态感应,务必确认设备带陀螺仪和加速度计。我踩过一个坑,RK3568的某款硬件默认没启用陀螺仪,导致AR画面转不动,查了半天才发现是设备硬件配置的问题,不是代码问题。
2.2 Flutter SDK与OpenHarmony侧的适配
开源鸿蒙跑Flutter,核心依赖的是OpenHarmony SIG组维护的flutter_flutter和flutter_engine仓库,而不是谷歌官方的Flutter SDK。这一点非常重要,很多人上来直接装官方Flutter,然后发现跑不了,搞了半天不知道原因是SDK本身不兼容。
正确的做法是,从gitee上拉取flutter_flutter仓库,切到适配OpenHarmony的分支,然后通过fvm或者直接配置PATH来管理版本。我这里用的是fvm,原因很简单——项目里可能同时存在多个Flutter版本,有些是给安卓用的,有些是给鸿蒙用的,用fvm可以按项目目录自动切换版本,省去手动改环境变量的麻烦。
拉取和切换的大致命令如下:
bash复制# 拉取OpenHarmony适配版Flutter SDK
git clone https://gitee.com/openharmony-sig/flutter_flutter.git
git checkout OpenHarmony-4.0-release
# 配置到fvm
fvm add custom /your/path/to/flutter_flutter
# 在项目根目录指定版本
fvm use custom
flutter_engine那边也一样,需要拉取源码自行编译Engine。编译Engine这个过程比较耗时,我第一次编了将近两个小时,机器配置一般的话建议预留一个晚上。不过好消息是,如果你只是做应用层开发,其实不需要自己编Engine,直接使用社区发布好的flutter引擎包就行。我在开发阶段用的是社区预编译版本,只有到最后要发布到特定设备时才自己编了一次。
2.3 Gradle配置与常见构建报错
说到构建,这里有一个热词里反复出现的问题:“you are applying flutter's main gradle plugin imperatively using the apply method”。这个问题在OpenHarmony适配版的Flutter里也会遇到,因为模板工程还是沿用了老式的Gradle插件应用方式。
出现这个报错时,不要慌,原因在于新版Gradle要求插件必须通过plugins块声明式应用,而不是用apply plugin这种方式。解决方案是把android/app/build.gradle里的插件应用改掉:
gradle复制// 修改前
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'dev.flutter.flutter-gradle-plugin'
// 修改后
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'dev.flutter.flutter-gradle-plugin'
}
注意,如果你用的是OpenHarmony适配版Flutter,工程结构里并不只有android目录,还有ohos目录。ohos目录下的构建脚本用的是hvigor,不是Gradle,所以这个报错实际上只影响android侧的编译。但问题在于,很多人第一次在DevEco Studio里打开Flutter工程时,IDE默认加载的是ohos侧的配置,同时又去解析android侧的build.gradle,两个构建系统混在一起,报错信息就容易让人摸不着头脑。
我的经验是:在DevEco Studio里开发鸿蒙Flutter应用时,不要手动去改android目录下的任何Gradle配置,因为OpenHarmony适配版Flutter在构建时并不依赖android目录。这个目录之所以存在,是为了保持Flutter工程结构的一致性,是给“跨平台”这个承诺留的后路。真正影响构建的,是ohos目录下的build-profile.json5和hvigor配置。
2.4 Visual Studio工具链报错的巧妙规避
热词里还有一条很典型:“vs code flutter android 项目报错: unable to find suitable visual studio toolc”。这个问题听起来很吓人,其实和VS Code完全无关,是Flutter的Windows桌面端开发时,需要通过Visual Studio来获取C++工具链,以便编译Windows runner。
如果你和我一样,主开发环境是Windows,但又主要针对OpenHarmony设备做开发,那么这个报错会在你执行flutter doctor或者flutter run -d windows时冒出来。规避方法有两种:
第一种,安装Visual Studio并勾选“使用C++的桌面开发”工作负载。这是一个笨办法,但胜在一劳永逸,以后想跑Windows桌面端也不慌。
第二种,既然我们做的目标是OpenHarmony设备,压根不需要Windows runner,那么你只需要确保flutter doctor里的“OpenHarmony”一项通过即可,其他平台的不通过可以忽略。
我个人的做法是把VS Code作为代码编辑器,但用DevEco Studio的命令行工具来做构建和部署,这样两者互不干扰,VS Code里那些平台相关的报错也不会影响实际开发流程。
3. AR太空探索应用的核心功能拆解
3.1 需求定位与功能边界
动笔写代码之前,我先给自己定了一个产品边界。AR太空探索应用,听起来很宏大,但一个Demo不可能真的去做星系漫游。我把功能收敛到三个核心场景:
第一,星空背景叠加。打开相机后,屏幕上叠加半透明的星空图层,让用户感觉“透过手机看到了宇宙”,这是AR沉浸感的入口。
第二,星球识别与展示。通过点击屏幕触发“探索”行为,在点击位置生成一个3D星球模型,模型可以旋转、缩放,展示基础信息和相关描述。
第三,传感器驱动的视角变换。用户转动手机时,星空背景和模型会依据陀螺仪数据做出对应的视差移动,这是AR应用“真实感”的关键所在。
这三个场景,涵盖了AR应用中最核心的三件事:相机画面获取、虚拟对象叠加、姿态感知。技术上不复杂,但链条很长——从相机权限到传感器数据读取,从3D模型渲染到Flutter的帧同步,每一个环节都可能出问题。把这个链路跑通,比实现一个花哨的AR游戏引擎更实用。
3.2 相机画面获取与Flutter侧对接
在OpenHarmony上获取相机画面,官方推荐的方式是使用AVCaptureSession,它对标的是Android的Camera2 API和iOS的AVFoundation。在Flutter里,我们没有现成的插件可以直接调用鸿蒙相机,所以通常的做法是:通过Platform Channel把相机的视频帧传给Flutter侧,在Flutter里用Texture或者自定义渲染来展示。
大致的流程是这样的:
- 在ohos侧实现一个CameraManager,使用AVCaptureSession创建相机会话;
- 设置输入源为后置摄像头,输出源为AVCapturePhotoOutput和AVCaptureVideoOutput;
- 通过Flutter的TextureRegistry注册一个纹理,把相机的视频帧写入纹理缓冲区;
- Flutter侧通过Texture widget来显示这个纹理。
代码层面,ohos侧关键的注册逻辑大概是:
typescript复制// ohos侧通过FlutterPlugin绑定纹理
let textureId = this.flutterPlugin.getTextureRegistry().createTexture(
new CameraTexture(frames)
);
// 将textureId传给dart侧
this.flutterPlugin.getEventChannel("camera_stream").send(textureId);
Flutter侧接受纹理后,用Texture(textureId: textureId)来渲染即可。这里有个很关键的坑:鸿蒙的相机帧格式默认是NV12或YUV,不是RGB,直接喂给Flutter的Texture会显示成绿油油一片。你需要把YUV转成RGBA,一般可以使用OpenHarmony提供的PixelMap接口来做转换,或者在Flutter侧用一个自定义的Fragment Shader来处理。为了性能考虑,我建议在ohos侧转换,毕竟Dart侧做像素级操作效率很低。
3.3 3D星球模型的渲染方案
AR太空探索应用要显示星球模型,渲染方案的选择很重要。我在调研阶段评估了两种方案:一是用Flutter生态里的3D渲染库,比如flutter_cube、model_viewer_plus这类;二是通过Platform Channel在ohos侧用原生渲染器渲染,再通过纹理桥接给Flutter。
我最后选了第二种方案,原因很现实:Flutter生态里的3D库在桌面和移动端跑跑还行,但在OpenHarmony上,它们依赖的OpenGL ES接口和Shader编译行为跟标准GLES不完全一致,兼容性问题很多。与其在Dart侧跟这些未知问题搏斗,不如在ohos侧用系统自带的图形接口做渲染,然后把渲染结果作为纹理帧送给Flutter。这本质上就是一个“远端渲染+画面合成”的架构,听起来复杂,但每一步都是可控的。
在ohos侧,我用的是系统自带的图形栈,加载一个简单的OBJ格式星球模型,用光照模型简单打光,然后渲染到FBO上,再把FBO的数据转成Image。这里有一个性能优化技巧:星球模型不需要每一帧都全分辨渲染,可以用一个固定分辨率比如512x512的FBO,然后在Flutter侧放大显示,视觉上差别不大,但GPU负载明显下降。
3.4 陀螺仪驱动视差效果
AR应用如果缺少姿态感应,用户转动手机时画面纹丝不动,沉浸感瞬间崩塌。所以视差效果必须做。实现方式不复杂:监听传感器的姿态角,换算成3D场景中相机或图层的偏移量,然后更新渲染参数。
ohos侧读取传感器使用的是@ohos.sensor接口:
typescript复制import sensor from '@ohos.sensor';
sensor.on(sensor.SensorId.GYROSCOPE, (data) => {
// data.x, data.y, data.z 为三轴角速度
this.onGyroscopeChange(data);
});
拿到角速度后,需要积分成角度。为了避免漂移,我采用了“角速度直接驱动偏移”的方案:不累积角度,而是每帧读取角速度值,映射到图层位移量上。比如x轴角速度为1 rad/s时,星空图层在x方向偏移50像素。这样在动态效果上近似真实姿态变化,同时规避了积分带来的累积漂移问题。
这个方案的问题在于,手机静止时角速度接近于0,画面也就静止了,不会因为重力方向变化而更新。这跟真实AR里“转动视角看到不同方向天空”的体验有差距。要修正的话,需要融合加速度计和陀螺仪,计算出绝对姿态角。开发基础版时可以先接受角速度方案,后续优化时再引入姿态融合算法。
3.5 用户交互与状态管理
交互层面,我用的是Flutter原生的GestureDetector,配合一个简单的状态管理器。点击屏幕时,记录点击位置在世界坐标系中的映射,然后触发星球生成动画。这里有一个值得注意的细节:屏幕点击坐标是二维的,但要映射到AR空间里,需要结合当前的相机姿态角,估算出一个合理的3D坐标。我用的方法是,假设点击位置对应的深度为5米,然后利用当前姿态角的逆矩阵,把屏幕坐标反投影到世界坐标。
状态管理我用的是Provider,因为项目里状态并不多,无非是“当前星球列表”“选中星球信息”“星空图层偏移量”这几个,用Provider足够,不需要引入Riverpod或Bloc这种重量级方案。
4. 实操过程与关键环节实现
4.1 从零搭建工程目录
整个项目按下述结构组织:
code复制ohos_flutter_ar/
├── ohos/ # OpenHarmony侧工程代码
│ ├── entry/src/main/
│ │ ├── ets/ # 原生实现
│ │ │ ├── camera/
│ │ │ ├── render/
│ │ │ └── sensor/
│ │ └── resources/
│ └── build-profile.json5
├── lib/ # Flutter侧代码
│ ├── main.dart
│ ├── pages/
│ │ └── home_page.dart
│ ├── widgets/
│ │ ├── camera_texture.dart
│ │ └── planet_view.dart
│ └── services/
│ ├── platform_bridge.dart
│ └── sensor_controller.dart
├── pubspec.yaml
└── fvm_settings.json
在DevEco Studio里新建工程时,要选“Empty Ability”模板,然后在模块目录下补上Flutter的lib目录和pubspec.yaml。注意,OpenHarmony适配Flutter的工程并不是标准的Flutter create生成的结构,你需要手动保证Flutter工具链能找到lib/作为入口目录。简单说,这一步不要依赖IDE自动生成,建议手动建立目录结构,再从flutter_flutter仓库的模板工程里拷贝android和ohos壳工程。
4.2 平台桥接的编写与调试
Flutter与ohos侧的通信,核心是MethodChannel和EventChannel。MethodChannel用于一次性请求,比如“打开相机”“获取当前设备传感器列表”;EventChannel用于持续数据流,比如“相机画面帧”“陀螺仪数据”。
ohos侧创建一个Plugin类,实现FlutterPlugin接口:
typescript复制export default class ArPlugin implements FlutterPlugin {
private channel: MethodChannel | null = null;
onAttachToEngine(flutterPluginBinding: FlutterPluginBinding): void {
this.channel = new MethodChannel(
flutterPluginBinding.getBinaryMessenger(),
'ar_planet/ar_plugin'
);
this.channel.setMethodCallHandler(this.handleMethodCall.bind(this));
flutterPluginBinding.getFlutterAssets();
}
private handleMethodCall(call: MethodCall, result: MethodResult): void {
switch (call.method) {
case 'startCamera':
this.startCamera(result);
break;
case 'createPlanet':
this.createPlanet(call.arguments as PlanetConfig, result);
break;
default:
result.notImplemented();
}
}
}
Dart侧对应的调用代码:
dart复制class PlatformBridge {
static const methodChannel = MethodChannel('ar_planet/ar_plugin');
static const eventChannel = EventChannel('ar_planet/ar_events');
Future<void> startCamera() async {
await methodChannel.invokeMethod('startCamera');
}
Future<int> createPlanet(PlanetConfig config) async {
final textureId = await methodChannel.invokeMethod('createPlanet', config.toMap());
return textureId as int;
}
}
调试阶段最常见的坑是MethodChannel名字拼错,或者两边类型不一致。比如ohos侧返回的是int,Dart侧却用String接收,运行时会直接抛MissingPluginException。建议在Dart侧写一个统一的错误处理包装,至少把channel调用异常打点到日志里,方便排查。
4.3 AR场景渲染闭环实现
整个AR渲染闭环是这样的:
- 相机启动后,ohos侧持续产生视频帧,通过纹理更新回调通知Flutter;
- Flutter的Texture widget重绘时,把当前帧显示出来;
- 陀螺仪数据通过EventChannel持续下发,Flutter侧维护一个最新的姿态角;
- 姿态角影响两个东西:星空图层的偏移量,以及相机Texture的轻微裁剪偏转;
- 用户点击屏幕,触发createPlanet调用,ohos侧生成一颗新星球纹理,Flutter侧添加新的Texture widget,并播放一个从屏幕中心飞入的动画。
这个闭环里,最考验性能的环节是“纹理更新”。Flutter的Texture机制在OpenHarmony适配版上默认是垂直同步的,如果ohos侧相机帧率是30fps,那么Flutter侧每秒钟会有30次纹理更新,这个频率对大多设备来说是OK的。但如果你做了分辨率很高的FBO渲染,或者同时存在多个3D模型,可能出现掉帧。我处理的办法是:动态调整相机输出的分辨率,在性能低的设备上自动降到640x480,在性能好的设备上保持1280x720。
4.4 性能调优与内存管理
AR应用最容易出问题的两个指标:帧率和内存。
帧率方面,我用了一个简单的性能探针,每秒钟统计实际渲染帧数并显示在调试面板上。如果发现低于25fps,就先检查是不是纹理更新过于频繁,其次检查是不是FBO分辨率过高,最后检查是否有内存泄漏导致的GC卡顿。
内存管理方面,有一个典型的坑:每次创建星球模型时,都要加载纹理和几何数据,如果创建完不主动释放,就会越积越多。用Flutter的Widget生命周期管理,在widget销毁时调用ohos侧的release资源接口,确保纹理和着色器程序被释放。
这里有一个小技巧:对于重复使用的星球模型,比如地球、火星这种经常被用户探索的目标,可以做缓存。第一次加载时把纹理放入LRU缓存,后续再创建时直接复用,避免重复加载的开销。实测下来,LRU缓存能把新建星球的耗时从80ms降低到10ms以内。
5. 实际开发中遇到的问题与解决方案
5.1 相机画面绿屏问题及修复路径
前面提过,鸿蒙相机输出的是YUV帧,直接渲染会绿屏。这个问题几乎每个做鸿蒙相机开发的都会遇到。我的修复方案是,在ohos侧把YUV转换成RGBA后再交给Texture。具体步骤如下:
- 使用PixelMap.createFromYUVComponent接口,把YUV帧转换成PixelMap;
- PixelMap转成PackingBuffer,拿到RGBA字节数组;
- 把这些字节写入到Texture的buffer里。
这个方法有个局限:PixelMap转换需要额外拷贝一次内存,相机分辨率越高,拷贝开销越大。如果你对性能要求很高,可以考虑使用OpenGL着色器来做YUV到RGB的GPU转换,一次draw call就能完成。我在Android侧用过类似方案,OpenHarmony上也有对应的EGL接口,只是需要多写一些原生代码。Demo阶段我用PixelMap方案,因为代码简洁、调试容易。
5.2 相机权限申请时机与Denied状态处理
OpenHarmony的权限模型是动态权限,需要在运行时申请。相机权限的ohos.permission.CAMERA属于user_grant类型,也就是必须用户手动确认。申请前需要在module.json5里配置声明:
json5复制{
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "用于实现AR相机预览",
"usedScene": {
"abilities": ["MainAbility"],
"when": "inuse"
}
}
]
}
注意,reason字段是必填的,不然应用市场上架审核过不了。在实际代码里,申请权限后如果用户拒绝了一次,再次进入相机页面时你需要引导用户去设置页开启权限。我这里的实现是:检测到权限是denied状态时,弹出一个对话框,提示用户去“设置 > 应用权限”手动开启。记得,不要在初始化阶段就去申请权限,而要等到用户点击“开始探索”按钮后再触发申请,这样用户的授权意愿更强,授权成功率更高。
5.3 Flutter引擎加载失败与多引擎冲突
在OpenHarmony上集成Flutter时,还有一个隐蔽的问题:如果应用里同时加载了多个Flutter引擎实例,可能造成资源冲突或内存翻倍。
我的项目里只用了一个FlutterEngine,通过FlutterEngine的复用机制来做页面间的切换。如果你打算在多个Ability里嵌入Flutter页面,要注意引擎创建和销毁的生命周期,尤其避免重复创建。
实际操作中,我发现DevEco Studio调试模式下的热重载对ohos侧的原生代码不起作用。也就是说,你改了ets代码后,需要重新编译整个hap包,而不能像纯Flutter开发那样指望hot reload。习惯了Flutter开发的人,在这里会撞几次墙,我在效率上也吃了不少亏。后来我养成了两套调试方案:纯UI调整用Dart侧hot reload,原生功能联调就完整编译。
5.4 低功耗蓝牙等外设适配思路
热词里有一条是“flutter 低功耗蓝牙ios有问题嘛”,说明很多人在做低功耗蓝牙相关的Flutter应用。虽然我的AR应用没有直接用蓝牙,但在太空探索的场景下,未来可能会接入智能望远镜设备做联动手势操作,所以我也简单调研过。
结论是:Flutter官方的flutter_blue_plus等插件在OpenHarmony上没有直接可用的实现,你需要通过Platform Channel把蓝牙能力从ohos侧暴露出来。在ohos侧,使用@ohos.bluetooth.bleManager接口来处理扫描、连接和特征值读写。这条路是通的,但需要有人花时间做适配,目前的社区插件覆盖情况还不乐观。
泛化地说,如果要在OpenHarmony上做Flutter开发,一定要记住一个原则:尽可能把底层设备能力下沉到ohos侧,Flutter侧只负责UI和业务逻辑。设备能力的差异化适配是绕不开的活,跨平台框架解决不了“系统接口不同”这件事,它只能解决“UI代码复用”这件事。
6. 项目总结与后续扩展思路
6.1 这个方案的核心价值与限制
回顾整个项目,我认为这套“开源鸿蒙+Flutter+AR”的组合,最大的价值在于让Flutter开发者在鸿蒙生态里拥有一个熟悉且高效的武器。Flutter本身的渲染引擎在OpenHarmony上运行得比我想像中稳定,虽然还存在热重载失效、部分插件不可用等问题,但核心的跨平台能力已经落地可用。
AR方面,必须承认OpenHarmony的AR生态还处于早期,没有类似ARCore或ARKit那样成熟的SDK。但这不代表不能做AR,通过相机+传感器+自定义渲染的组合,我们依然可以实现基础但完整的AR体验。对于AR游戏、AR教育、AR导览这类场景,这些基础能力其实已经可以支撑起早期的产品原型。
限制也存在,主要有三点:一是相机和传感器的高精度同步机制不成熟,做精密AR测量会很难;二是3D渲染链路的性能优化空间比较有限,复杂模型加载依然吃力;三是社区生态还不够,遇到问题很多时候只能自己翻源码,坑都得自己填。
6.2 可扩展方向:从Demo到可用产品
如果想把Demo做成能上架的产品,我认为有以下几个优先级很高的扩展方向:
第一,接入真·姿态融合算法。当前角速度驱动视差的方案在体验上还是单薄,建议融合加速度计+陀螺仪,用互补滤波或Madgwick算法计算出绝对姿态角。这块有大量现成的算法代码可以移植,计算量也不大,但要针对OpenHarmony的传感器采样特性做调参。
第二,实现更强的行星渲染理念。单纯一个贴图模型,很容易被用户看穿是“假3D”。建议引入法线贴图和简单的多光源光照模型,让星球表面有更真实的凹凸感和光影变化,会显著提升观感。
第三,增加“星空知识库”内容层。AR探索应用的黏性依赖内容,做好看不如做有用。可以把天体数据库接入进来,用户指向哪颗星,就能显示它的距离、质量、构成等知识卡片。这个方向的技术难度不大,但内容运营的工作量不小。
第四,分布式能力联动。开源鸿蒙区别于安卓和iOS的最大特色就是分布式软总线。如果AR应用能把手机构建的AR场景流转到电视或Pad等大屏上,形成一个“小屏探索、大屏展示”的联动体验,产品的差异化会非常明显。这部分的接口调通不难,但需要多设备联调,时间和硬件成本不低。
6.3 我的一些实际心得
做这个项目最大的体会是,跨平台开发的价值不在“一套代码跑所有平台”这句话,而在于把团队的知识资产沉淀在一个抽象层之上。Flutter对鸿蒙的价值,不只是UI跨端,更是让前端团队无需学习数十个原生API就能参与到鸿蒙应用开发中来。
如果你要复刻这个项目,我给三条建议。第一,先把设备环境弄对,OpenHarmony的开发板和模拟器在功能支持上有明显差距,选定目标设备后再设计功能,不要反过来。第二,原生侧和Flutter侧的边界要划清楚,桥接层的代码要保持极简,每新增一个原生能力时先做好接口文档,避免两边开发者互相踩脚。第三,不要迷信社区预编译产物,涉及性能和底层渲染时,自己编译引擎、自己调试渲染管线才能真正掌控问题,这个时间省不得。
AR本质上是一个系统工程,它考验的不是某一个平台或框架的能力上限,而是你对场景需求、设备约束、用户体验的综合判断力。开源鸿蒙把这个判断力的考验又往前推了一步——因为一切都要你自己动手,但恰恰是这种“造轮子”的过程,让开发者对系统的理解比以往任何时候都更深。
