C-API 版本使用XComponent总共分成了两个步骤:

  1. createSurface的时候创建XComponentSurface;
  2. startSurface的时候将CPP的XComponentSurface连接到ArkUI的Xcomponent上。

createSurface的时候主要做了以下的操作:

  1. 创建并将XComponentSurface记录到Map中:

    void RNInstanceCAPI::createSurface(facebook::react::Tag surfaceId, std::string const& moduleName) {
      m_surfaceById.emplace(
        surfaceId,
        XComponentSurface(
          // ···
        surfaceId,
        moduleName)
      );
    }
  2. 在XComponentSurface中创建rootView,用于挂载C-API的组件,并在Surface上统一处理Touch事件:

    XComponentSurface::XComponentSurface(
    //···
    SurfaceId surfaceId,
    std::string const& appKey)
    : 
      //···
      m_nativeXComponent(nullptr),
      m_rootView(nullptr),
      m_surfaceHandler(SurfaceHandler(appKey, surfaceId)) {
        m_scheduler->registerSurface(m_surfaceHandler);
        m_rootView = componentInstanceFactory->create(
          surfaceId, facebook::react::RootShadowNode::Handle(), "RootView");
        m_componentInstanceRegistry->insert(m_rootView);
        m_touchEventHandler = std::make_unique<SurfaceTouchEventHandler>(m_rootView);
      }

startSurface的时候主要做了以下的操作:

  1. 在ArkTS侧创建XComponent,并设置id,type与libraryname属性。其中:

    • id:组件的唯一标识,又由InstanceID和SurfaceID共同组成,记录了此XComponent属于哪一个Instance与Surface;
    • type:node,标识该XComponent是一个占位组件,组件的实现都在C-API侧;
    • libraryname:表示C-API组件在哪个so库中实现,并加载该so库,自动调用该so中定义的Init函数。当前React Native for OpenHarmony默认的so名字rnoh\_app。

      XComponent({
          id: this.ctx.rnInstance.getId() + "_" + this.surfaceHandle.getTag(),
          type: "node",
          libraryname: 'rnoh_app'
      })
  2. 在CPP侧的Init中调用registerNativeXComponent函数,该函数中调用了OH\_NativeXComponent\_GetXComponentId用于获取ArkTS设置的id,并根据id找到对应的Instance与Surface。同时还要获取nativeXComponent对象,记录ArkTS侧的XComponent。

    if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) !=
      OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        ···
    }
    std::string xcomponentStr(idStr);
    std::stringstream ss(xcomponentStr);
    std::string instanceId;
    std::getline(ss, instanceId, '_');
    std::string surfaceId;
    std::getline(ss, surfaceId, '_');
  3. 调用OH\_NativeXComponent\_AttachNativeRootNode,将XComponentSurface中记录的rootView连接到ArkTS侧的XComponent上:

    OH_NativeXComponent_AttachNativeRootNode(
        nativeXComponent,
        rootView.getLocalRootArkUINode().getArkUINodeHandle());

HarmonyOS码上奇行
5k 声望2.5k 粉丝