OpenHarmony开发者论坛
标题:
Native API应用开发 之 使用NDK接口构建UI
[打印本页]
作者:
马迪
时间:
2024-7-30 19:58
标题:
Native API应用开发 之 使用NDK接口构建UI
[md]# 背景
目前,OpenHarmony/HarmonyOS Next的主要UI开源三方库,如lottie,imageknife,pulltorefresh都是使用arkts自定义组件开发的。但越来越多应用除了功能对功能的要求外,现在也开始提出性能的要求。所以被迫得提前研究下使用NDK接口构建开源三方库。
ArkUI开发框架提供了一系列NDK接口,能够在应用中使用C和C++代码构建UI界面,这些接口包括UI组件创建、UI树操作、属性设置和事件监听等。在OpenHarmony 5.0文档中,我找到了如何使用[NDK接入ArkTS页面](
https://docs.openharmony.cn/page ... s-the-arkts-page.md
),如何[使用NDK构建自定义组件](
https://docs.openharmony.cn/page ... ustom-components.md
)。 通过参考上述文档,我大概了解了如何在ArkTS页面嵌入一个NDK接口实现的自定义组件,并嵌入了一个系统Image组件。
具体效果如下,可以看到使用ndk可以实现与arkTS库一样的Image系统组件,加载网络图片:
![200732lq85ssk7v8zkq8bb.png](
https://forums-obs.openharmony.c ... 9hmj1j1ls9cayw7.png
"200732lq85ssk7v8zkq8bb.png")
# 代码实现
1.使用NDK自定义组件,内部嵌入一个Image组件,并提供设置url的方法:
```
#include "ArkUINode.h"
namespace NativeModule {
class CustomImageNode : public ArkUINode {
public:
// 使用自定义组件类型ARKUI_NODE_IMAGE创建组件。
CustomImageNode()
: ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_IMAGE)) {
}
~CustomImageNode() override {
}
// 设置图片地址
void SetImageUrl(const char* url) {
ArkUI_AttributeItem item = { .string = url};
NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(this->handle_, NODE_IMAGE_SRC , &item);
}
};
} // namespace NativeModule
```
2.实现napi方法,对arkTS暴露创建ndk组件createNativeRoot和销毁ndk组件destroyNativeRoot的方法
```
namespace NativeModule {
napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// 获取NodeContent
ArkUI_NodeContentHandle contentHandle;
OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
NativeEntry::GetInstance()->SetContentHandle(contentHandle);
auto customNode = std::make_shared<CustomImageNode>();
customNode->SetImageUrl("http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg");
customNode->SetWidth(200);
customNode->SetHeight(200);
// 保持Native侧对象到管理类中,维护生命周期。
NativeEntry::GetInstance()->SetRootNode(customNode);
return nullptr;
}
napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
// 从管理类中释放Native侧对象。
NativeEntry::GetInstance()->DisposeRootNode();
return nullptr;
}
} // namespace NativeModule
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr},
{"destroyNativeRoot", nullptr, NativeModule:
estroyNativeRoot, nullptr, nullptr, nullptr, napi_default,
nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
```
3.inded.d.ts声明createNativeRoot和destroyNativeRoot方法
```
export const createNativeRoot: (content: Object) => void;
export const destroyNativeRoot: () => void;
```
4.ArkTS嵌入组件,在aboutToAppear里加载,在aboutToDisappear里卸载
```
import nativeNode from 'libentry.so';
import { NodeContent } from '@ohos.arkui.node';
@Entry
@Component
struct Index {
private rootSlot = new NodeContent();
aboutToAppear(): void {
// 传递NodeContent对象用于Native创建组件的挂载显示
nativeNode.createNativeRoot(this.rootSlot)
}
aboutToDisappear(): void {
// 销毁NativeModule组件
nativeNode.destroyNativeRoot()
}
build() {
Column() {
Text("ArkTs组件").fontSize(30)
Image("http://h.hiphotos.baidu.com/image/pic/item/902397dda144ad340668b847d4a20cf430ad851e.jpg").width(200).height(200)
Blank().height(100)
Text("NDK组件").fontSize(300)
// 将NodeContent和ContentSlot占位组件绑定。
ContentSlot(this.rootSlot)
}
.width('100%')
.height('100%')
}
}
```
5.CMakeLists增加对libace\_ndk.z.so的链接
```
target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so)
```
【完整demo参考】
[
https://gitee.com/MaDiXin/ndksample
](
https://gitee.com/MaDiXin/ndksample
)
欢迎交流与探讨
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5