【鸿蒙南向开发】Native API应用开发 之 使用NDK接口构建UI

199 篇文章 8 订阅
198 篇文章 0 订阅

【背景】
目前,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系统组件,加载网络图片:
image.png

【核心代码解读】

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/

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值