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