20241212更新
ArkUIX迁移了仓库,迁到了gitcode gitcode.com/ArkUI-X
介绍
ArkUI-X是一个声明式UI开发框架,可以让我们使用ArkTS写跨端UI,目前支持OpenHarmony、HarmonyOS、Android、iOS四个平台
设计总体说明
总体视图
设计思路如下:
- 采用 C++ 编写整体后端引擎代码,保持在多平台的可移植性,最小化平台依赖,降低平台移植成本。
- 整体绘制采用自渲染机制,降低平台依赖,同时进一步提升绘制效果的一致性。
- 抽象出平台适配层以及平台桥接层,以便不同平台的适配。
跨平台技术
- 研发模型,兼容OpenHarmony应用的Stage开发模型,支持基于ArkTS的声明式开发范式,可跨平台。
- 声明式UI后端引擎,包括布局,渲染,C++ UI组件,事件机制等,可跨平台。
- API扩展机制,基于NAPI机制,可跨平台。 不同平台需要各自扩展具体的API实现。
- 工具链/SDK, 工具链可跨平台,SDK需基于不同平台构建
- ArkUI依赖的ArkTS引擎以及图形引擎,也可跨平台
构建系统
ArkUI-X编译构建提供了一套基于GN和Ninja的编译构建框架
- 基础构建基于OpenHarmony的build仓
- 在OpenHarmony构建基础上新增Android和iOS编译工具链,以支持ArkUI跨平台SDK编译输出
SDK结构设计
ArkUI-X SDK目录结构介绍 gitee.com/arkui-x/doc…
启动入口
开发框架对应平台语言实现的Entrance,提供不同平台的基础入口环境
以Android为例
Stage模型下,Ability生命周期的入口为StageAbility,生命周期一直会通知到JsAbility,执行用户的生命周期回调方法,UI的页面是在onWindowStageCreated
的生命周期中,调用Window的loadContent
接口进行加载,创建ArkUI的实例并初始化渲染管线,将页面进行渲染显示
API扩展机制
JS API扩展机制,用于Native接口能力暴露到JS层,该机制直接复用OpenHarmony上的统一封装机制,扩展API (C++实现),并实现部分内置API
JS API需要遵循OpenHarmony的API定义,在不同平台上通过API扩展机制进行扩展。
环境配置
配置开发环境 gitee.com/arkui-x/doc…
下载DevEco Studio
developer.huawei.com/consumer/cn…
配置OpenHarmonySDK
点击Edit指定下载目录,等待下载完成
配置Android SDK安装目录环境变量
配置环境变量ANDROID_HOME,设置Android SDK安装目录
export ANDROID_HOME=$HOME/Library/Android/sdk
配置 ArkUIX SDK
点击Edit指定下载目录,等待下载完成
配置ACE Tools(非必选)
如果你需要使用命令行打包和编译,可以配置ACE Tool。主要是配置OHPM和ARKUIX_SDK_HOME环境变量
配置环境变量
export ARKUIX_SDK_HOME=/path-to-arkui-x-sdk
export PATH=${ARKUIX_SDK_HOME}/版本/arkui-x/toolchains/bin:$PATH
我这里是配置到了~/Documents/huawei/arkuix_sdk
# Android sdk
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
# 华为
export DecEcoIDE_SDK_Home=/Applications/DevEco-Studio.app/Contents
## 这里DEVECO_SDK_HOME名字不能改,ace需要使用到
export DEVECO_SDK_HOME=$DecEcoIDE_SDK_Home/sdk
# HDC_SERVER_PORT和HDC_SDK_PATH 是hdc需要配置的环境变量
export HDC_SERVER_PORT=7035
export HDC_SDK_PATH=$DEVECO_SDK_HOME/HarmonyOS-NEXT-DB1/openharmony/toolchains
export PATH=$HDC_SDK_PATH:$PATH
export PATH=$DecEcoIDE_SDK_Home/tools/hvigor/bin:$PATH
export PATH=$DecEcoIDE_SDK_Home/tools/ohpm/bin:$PATH
# 引入@arkui-x.bridge的时候需要用到
## 这里ARKUIX_SDK_HOME名字不能改,ace需要使用到
export ARKUIX_SDK_HOME=${HOME}/Documents/huawei/arkuix_sdk
export PATH=$ARKUIX_SDK_HOME/12/arkui-x/toolchains/bin:$PATH
# 仓颉
export CANGJIE_HOME=${HOME}/Documents/cangjie/cangjie
export PATH=${CANGJIE_HOME}/bin:${CANGJIE_HOME}/tools/bin:$PATH
hw_arch="aarch64"
export DYLD_LIBRARY_PATH=${CANGJIE_HOME}/runtime/lib/darwin_${hw_arch}_llvm:${DYLD_LIBRARY_PATH}
应用开发
应用开发指导 gitee.com/arkui-x/doc…
第一个例子
使用DevEco Studio创建一个空的ArkUI-X工程
进行编译输出
编译后的ArkTS代码、资源和平台胶水代码已生成到Android和iOS应用工程中
应用包结构
ArkUI-X应用目录结构设计思想
- 从OpenHarmony应用工程原生支持跨平台角度出发,在OpenHarmony应用工程之上叠加Android和iOS应用工程
- ArkTS代码和resources资源编辑仍在OpenHarmony侧完成
- Native代码在各自平台应用工程中完成
ArkUI-X应用工程结构说明 gitee.com/arkui-x/doc…
编译构建说明
ArkTS源码
ArkTS源码通过OpenHarmony SDK工具链生成abc(Ark Byte Code) ,并分别拷贝到Android和iOS应用工程,作为平台应用资源进行管理。
ArkUI应用资源
ArkUI Resources资源也通过OpenHarmony SDK工具链进行编译,编译后的ArkUI资源分别拷贝到Android和iOS应用工程,作为平台应用资源进行管理。
ArkUI框架资源
ArkUI框架资源随ArkUI-X SDK进行发布,应用构建时会自动打包到ArkUI-X应用中,可保证ArkUI-X应用在各平台上UX渲染一致性。
综上所述,Android平台上通过assets管理ArkTS编译产物、ArkUI应用资源和ArkUI框架资源,iOS平台上通过Bundle Resources管理ArkTS编译产物、ArkUI应用资源和ArkUI框架资源
注意点
Ability开发说明 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/quick-start/start-with-ability-on-ios.md
StageViewController是Stage模型iOS端视图控制器基类,若要实现跨平台基础能力及触发对应ability生命周期,所有iOS端应用级别的视图控制器均要继承于StageViewController
StageApplication本质上是一个调度类,主要用于触发内部相关类实现路径解析与配置、注册应用相关的configuration信息、触发ability部分生命周期事件等
通过Stage模型开发iOS端应用指南 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/quick-start/start-with-ability-on-ios.md
iOS端应用info配置里的bundleName需要与Ability的bundleName一致。
iOS端应用内的viewController的viewControllerName组成规则:Ability的moduleName + Ability的abilityName + “viewController”。
虽然这样说,但并不一定这样
从ArkUIX调用原生页面
ArkUI-X代码,调用startAbility后会走到原生代码的生命周期回调内
在iOS上会回调到下面的方法中。然后在方法中解析出bundleName、moduleName、abilityName。根据匹配调用对应的VC,调用哪个VC就是我们自己处理的了。
所以说上面 iOS端应用内的viewController的viewControllerName组成规则:Ability的moduleName + Ability的abilityName + “viewController”。这个规则可以不遵守,当然为了明确哪个VC遵守也没问题
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
从原生调用ArkUIX页面
原生端按照原生的push方式,打开一个ArkUIX页面。有几点要求
-
打开的VC是继承于StageViewController
-
传入的instanceName需要包含完整的 bundleName:moduleName:abilityName,这里是为了让ArkUIX找到要加载的资源
-
传入的params格式有要求
- 最外层是一个字典,字典内params是一个数组
- 数组中每一个元素是一个对象,每个对象包含key、value、type三个字段,分别表示传递的参数名称、参数值、参数类型
- 最后,对这个字典进行序列化成json字符串
ArkUI-X侧,通过Ability的onCreate或onNewWant接受传递过来的参数,然后我们就可以通过参数来确定加载哪个page,从而实现打开容器的某一页
桥接插件开发
开发者文档 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/README.md
平台桥接(@arkui-x.bridge) gitee.com/arkui-x/doc…
iOS 平台桥接开发指南 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/tutorial/how-to-use-bridge-on-ios.md
iOS ArkUI-X插件开发指南 gitee.com/arkui-x/doc…
Android 平台桥接开发指南 gitee.com/arkui-x/doc…
Android ArkUI-X插件开发指南 gitee.com/arkui-x/doc…
插件的通信机制和RN很类似
- 在原生端,通过调用addPlugin添加插件,在插件里通过名称注册对应的BridgePlugin
#pragma mark - IMessageListener ArkUI侧发送的消息代理实现
/**
* Arkui测调用sendMessage 发送消息到IOS测,将会触发次方法的回调
* @param data Arkui 传递过来的数据
* return 返回值传递传递给Arkui测
*/
- (NSString*)onMessage:(id)data {
NSLog(@"onMessage data: %@", data);
return [NSString stringWithFormat:@"监听到:ArkTS给Native发送数据成功,发送的数据是 %@", data];
}
/**
* iOS 通过sendMessage 方法发送消息到Arkui, Arkui成功接到消息后回调此方法传递结果
* @param data Arkui 返回的信息
*/
- (void)onMessageResponse:(id)data {
NSLog(@"onMessageResponse data: %@", data);
// [self sendMessage:[NSString stringWithFormat:@"监听到:Native调用ArkTS方法%@ 成功,方法的返回值是 %@",
// methodName,
// resultValue ?: @"空"]];
}
#pragma mark - IMethodResult 用于监听平台侧调用ArkUI侧注册的方法的执行情况
/**
* ArkUI侧调用unRegisterMethod方法时将触发该接口,用于通知平台侧事件被注销了。
* @param methodName ArkUI侧方法的名称
* @param resultValue ResultValue 类 ,并将ArkUI侧方法的返回值传递给平台侧
*/
- (void)onSuccess:(nonnull NSString *)methodName resultValue:(nonnull id)resultValue {
if (resultValue) {
NSLog(@"bridge onSuccess data: %@", resultValue);
}
[self sendMessage:[NSString stringWithFormat:@"监听到:Native调用ArkTS方法%@ 成功,方法的返回值是 %@",
methodName,
resultValue ?: @"空"]];
}
/**
* 平台侧调用ArkUI侧定义方法时,如果出错则触发该接口,并将出错信息返回平台侧。具体错误码查看ResultValue类中错误码或者接口文档
* @param methodName ArkUI侧方法的名称
* @param errorCode 错误码
* @param errorMessage 错误信息
*/
- (void)onError:(nonnull NSString *)methodName errorCode:(ErrorCode)errorCode errorMessage:(nonnull NSString *)errorMessage {
NSLog(@"Bridge: onError: %@ errorCode: %d errorMessage: %@",methodName, errorCode, errorMessage);
[self sendMessage:[NSString stringWithFormat:@"监听到:Native调用ArkTS方法%@ 失败,失败信息是 %@",
methodName,
errorMessage ?: @"空"]];
}
/**
* ArkUI侧调用unRegisterMethod方法时将触发该接口,用于通知平台侧事件被注销了。
* @param methodName ArkUI侧方法的名称
*/
- (void)onMethodCancel:(nonnull NSString *)methodName {
NSLog(@"Bridge: onMethodCancel");
[self sendMessage:[NSString stringWithFormat:@"监听到:ArkTS调用unregisterMethod取消了注册的方法%@",
methodName]];
}
在ArkTS端通过 @arkui-x.bridge的API使用名称调用createBridge创建一个插件
5. 然后原生和ArkTS调用相应的API进行通信
支持动态化
动态化介绍 gitee.com/arkui-x/doc…
总体分成两类
- 框架动态化:指ArkUI跨平台开发框架本身可以做到动态下发,即应用发布时可以不带框架基础库,降低应用原始发布包体积,在需要时才从云端动态下发和执行加载;
- 特性动态化:指用ArkTS语言开发的特性可以做到动态化,和宿主应用解耦,独立发布、升级版本;
框架动态化是指依赖的动态库可以动态下载,只有Android支持,iOS不支持
特性动态化是指作为资源的abc文件和对应的文件资源,module等
不完全的API支持
支持的组件范式
除鸿蒙特有的组件外,基本所有组件都能支持。支持占比90%左右
ArkUIX 支持API developer.huawei.com/consumer/cn…
鸿蒙原生API gitee.com/arkui-x/doc…
支持的接口
ArkUIX支持的接口大概占鸿蒙的70%左右,其中的剩余部分主要是ArkUI以及鸿蒙的独有能力
资料
- ArkUI-X 仓库 gitee.com/arkui-x
- ArkUI-X SDK目录结构介绍 gitee.com/arkui-x/doc…
- 2.0.0-beta1发布说明 https://gitee.com/arkui-x/docs/blob/master/zh-cn/release-notes/ArkUI-X-v2.0.0-beta1.md
- ArkUI-X应用适配层 gitee.com/arkui-x/app…
- iOS平台的适配层 gitee.com/arkui-x/ark…
- iOS ArkUI-X 插件开发 gitee.com/arkui-x/doc…
- 联动编译 gitee.com/arkui-x/doc…
- Android平台的适配层 gitee.com/arkui-x/ark…
- Android ArkUI-X 插件开发 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/tutorial/how-to-use-arkui-x-plugin-on-android.md
- 官方提供的一些插件 gitee.com/arkui-x/plu…
- ArkUI-X 应用开发 https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/README.md
- ArkUI-X 文档 gitee.com/arkui-x/doc…