【背景】
目前,OpenHarmony/HarmonyOS Next的主要UI开源三方库,如lottie,imageknife,pulltorefresh都是使用arkts自定义组件开发的。但越来越多应用除了功能对功能的要求外,现在也开始提出性能的要求。所以被迫得提前研究下使用NDK接口构建开源三方库。
ArkUI开发框架提供了一系列NDK接口,能够在应用中使用C和C++代码构建UI界面,这些接口包括UI组件创建、UI树操作、属性设置和事件监听等。在OpenHarmony 5.0文档中,我找到了如何使用NDK接入ArkTS页面,如何使用NDK构建自定义组件。 通过参考上述文档,我大概了解了如何在ArkTS页面嵌入一个NDK接口实现的自定义组件,并嵌入了一个系统Image组件。
具体效果如下,可以看到使用ndk可以实现与arkTS库一样的Image系统组件,加载网络图片:
【核心代码解读】
1.使用NDK自定义组件,内部嵌入一个Image组件(类型为ARKUI_NODE_IMAGE),并提供设置url的方法:
2. #include "ArkUINode.h"
4. namespace NativeModule {
6. class CustomImageNode : public ArkUINode {
7. public:
8. // 使用自定义组件类型ARKUI_NODE_IMAGE创建组件。
9. CustomImageNode()
10. : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_IMAGE)) {
11. }
13. ~CustomImageNode() override {
14. }
16. // 设置图片地址
17. void SetImageUrl(const char* url) {
18. ArkUI_AttributeItem item = { .string = url};
19. NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->setAttribute(this->handle_, NODE_IMAGE_SRC , &item);
20. }
21. };
23. } // 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::DestroyNativeRoot, 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(30)
// 将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)
写在最后
●如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
●更多鸿蒙最新技术知识点,请移步前往小编:https://gitee.com/