赞
踩
部分应用的主要开发语言为C/C++,但是HarmonyOS的部分接口仅以ArkTS的形式暴露,因此需要将ArkTS的接口封装为Native接口。本例以DocumentViewPicker的Select方法为例,提供了Napi封装ArkTS API的通用方法,本例包含内容如下:
测试说明:
集成说明:
使用说明:
native侧需要主动调用ets侧的代码,需要将ets侧代码注入到native侧,并在注册时创建函数的引用及线程安全函数,并保存当前线程(js线程)的id及env供后续调用时使用
ets侧:
etswrapper.registryDocumentViewPickerFn(documentViewPickerSelect, documentViewPickerSave);
native侧:
NODE_API_CALL(env, napi_create_threadsafe_function(env, args[0], nullptr, selectWork, 0, 1, nullptr, nullptr,
nullptr, tsfn::callJSSelect, &(uniContext->selectTsfn)));
NODE_API_CALL(env, napi_create_threadsafe_function(env, args[1], nullptr, saveWork, 0, 1, nullptr, nullptr,
nullptr, tsfn::callJSSave, &(uniContext->saveTsfn)));
NODE_API_CALL(env, napi_create_reference(env, args[0], 1, &(uniContext->selectRef)));
NODE_API_CALL(env, napi_create_reference(env, args[1], 1, &(uniContext->saveRef)));
uniContext->pickerEnv = env;
uniContext->jsThreadID = fns::getCurrentThreadID();
if (uniContext->jsThreadID != fns::getCurrentThreadID()) {
status = napi_acquire_threadsafe_function(uniContext->selectTsfn);
status = napi_call_threadsafe_function(uniContext->selectTsfn, selectParam, napi_tsfn_blocking);
std::unique_lock<std::mutex> unil(uniContext->resultWaitUtil.lock);
uniContext->resultWaitUtil.cv.wait(unil, [] { return uniContext->resultWaitUtil.isFinished; });
return;
} else {
status = napi_call_function(uniContext->pickerEnv, nullptr, tsSelect, 4, args, &result);
}
DocumentViewPickerSelectParam *selectParam = new DocumentViewPickerSelectParam(options, thenWrapper, catchWrapper)
因为本例中的filepicker是异步的,回调函数需要调用者传入,而napi中若需要将native方法直接封装为ets方法对于函数类型是有要求的。因此这里通过将回调函数封装到对象中,通过对象包装来实现将一般类型的函数封装为ets侧的函数:
native侧:
// step:类型声明 class DocumentViewPickerSelectThenCbWrapper { public: documentSelectThenFn thenFn; DocumentViewPickerSelectThenCbWrapper(documentSelectThenFn fn) : thenFn(fn) {} /** * 将对象实例包装为js对象 */ napi_value convert2NapiValue(napi_env env); /** * 参数是string[],这里面会调用thenFn,ets侧调用 */ static napi_value call(napi_env env, napi_callback_info info); }; // step2:convert2NapiValue方法实现 napi_value etswrapper::DocumentViewPickerSelectThenCbWrapper::convert2NapiValue(napi_env env) { napi_value object; DocumentViewPickerSelectThenCbWrapper *thenWrapper = new DocumentViewPickerSelectThenCbWrapper(this->thenFn); NODE_API_CALL(env, napi_create_object(env, &object)); NODE_API_CALL(env, napi_wrap( env, object, thenWrapper, [](napi_env env, void *finalize_data, void *finalize_hint) -> void { delete reinterpret_cast<DocumentViewPickerSelectThenCbWrapper *>(finalize_data); }, nullptr, nullptr)); napi_property_descriptor desc[] = { {"call", nullptr, DocumentViewPickerSelectThenCbWrapper::call, nullptr, nullptr, nullptr, napi_default, nullptr}, }; NODE_API_CALL(env, napi_define_properties(env, object, sizeof(desc) / sizeof(*desc), desc)); return object; } // step3:call方法实现 napi_value etswrapper::DocumentViewPickerSelectThenCbWrapper::call(napi_env env, napi_callback_info info) { // ... napi_value thisArg; NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr)); DocumentViewPickerSelectThenCbWrapper *thenWrapper; NODE_API_CALL(env, napi_unwrap(env, thisArg, reinterpret_cast<void **>(&thenWrapper))); // ... thenWrapper->thenFn(data); return nullptr; }
ets侧:
function documentViewPickerSelect(uiContext: UIContext, options: picker.DocumentSelectOptions, thenWrapper:
StringArrayThenCbWrapper, catchWrapper: CatchCbWrapper): void {
let documentViewPicker: picker.DocumentViewPicker = new picker.DocumentViewPicker();
documentViewPicker.select(options).then((value: string[]) => {
thenWrapper.call(value);
}).catch((error: BusinessError) => {
// ...
})
}
// step1:
windowStage.on("windowStageEvent", (data: window.WindowStageEventType) => {
if (data === window.WindowStageEventType.ACTIVE) {
etswrapper.setTopAbilityID(abilityID);
}
}
// step2:
function documentViewPickerSelect(uiContext: UIContext, options: picker.DocumentSelectOptions, thenWrapper:
StringArrayThenCbWrapper, catchWrapper: CatchCbWrapper): void {
uiContext.runScopedTask(() => {
// ...
})
}
dragtoswitchpictures // har包
|---cpp // cpp源码
| |---include // 头文件
| |---src // 源码
|---ets/view
| |---MockNativeCallPickerView.ets // 模拟cpp侧发起调用
|---ets/wrapper
| |---wrapper.ets // 封装的js方法
不涉及
|->焦点切换->on事件分发
多模事件输入->窗口管理
|->arkui->button事件触发
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr18.cn/F781PH
https://qr18.cn/F781PH
1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向
https://qr21.cn/D2k9D5
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。