鸿蒙如何在Native调用ArkTS方法
作者: Mike98
责任编辑: 耿立影
来源: 专栏
时间: 2025-11-21 15:03
关键字: 鸿蒙 ArkTS
浏览: 2317
点赞: 128
收藏: 11
鸿蒙作为一款新兴的智能操作系统,现在适配鸿蒙系统的应用越来越多,同时会面临三端兼容问题,如同一产品功能,需要维护iOS、Android、鸿蒙三端代码。
拿文件上传、下载功能场景举例,同时要适配iOS、Android、鸿蒙三端,目前比较好的方案是文件上传、下载功能下沉到C,三端native代码可以复用,但是在鸿蒙上存在如下一个问题:
Native文件上传、下载进度怎么从Native线程异步回调给ArkTs线程对应JS回调方法?
答案:通过Node-API提供的线程安全函数,可以把文件上传、下载进度从native线程异步回调ArkTs线程JS回调方法。
Node-API(以前称为 N-API)是用于构建native功能的API,它独立于底层的JavaScript引擎(例如 V8引擎),并作为 Node.js 本身的一部分进行维护。
Node.js是JavaScript运行时环境,用来支持JS代码的执行,HarmonyOS Native API对Node-API的接口进行了封装和重写,支持Node-API标准款的部分接口,以此提供ArkTS/JS与C/C++模块之间交互能力。
Node-API必须遵循一个原则: Node-API的调用必须和JS的调用线程一致。
1)Node-API接口只能在JS线程使用,JS调用Native的线程才能调用Node-API接口,Native子线程无法调用;
2)napi env是无法跨线程使用,如果使用全局变量将napi env保存下来,再在其他线程使用会崩溃。
上面提到的文件上传场景,文件上传是在native子线程,非JS线程,如果使用Node-API,必然会崩溃,但Node-API提供线程安全函数,通过线程安全函数可以在native线程里回调JS线程。
3.1 线程安全函数
线程安全函数ThreadSafeFunction(简称TFS)为了解决跨线程的函数调用问题,可以将普通的JS函数封装成线程安全函数,包装之后的函数是允许在线程之间传递,线程安全函数的定义
使用TFS一般分为如下几步:step1:native侧创建线程安全函数,绑定ArkTs的API的callback和线程安全回调函数call\_js\_cb;
step2:native子线程执行异步任务,并在子线程中调用napi_call_threadsafe_function,将call_js_cb抛到事件循环中进行调度;
step3:在call_js_cb中通过调用napi_call_function将native异步任务的结果回调给ArkTs线程,进行相关的UI刷新操作。
3.2 EventLoop事件循环
Libuv是由C语言编写的,基于事件驱动的异步I/O库,利用编译好的libuv库文件,可以写一个简单事件驱动的例子:
线程安全函数是怎么实现主线程、线程之间通信?
libuv通过循环不断取出watcher队列中的事件,uv__iot_t结构体保存了文件描述符,其对应一个事件和事件回调,通过uv__iot_t结构体来初始化 epoll_event,再使用epoll_wait来等待文件描述符上I/O事件,事件触发之后调用对应的回调函数,通过epoll实现线程间的通信。
| API | 解释 |
|---|---|
| uv_run(uv_loop_t* loop, uv_run_mode mode) | 运行事件循环,有如下几种mode:UV_RUN_DEFAULT:运行事件循环直到没有更多的活动的和被引用到的句柄或请求UV_RUN_ONCE:轮询I/O一次 UV_RUN_NOWAIT:轮询I/O一次但不会阻塞,如若没有待处理的回调函数时 |
| uv_loop_alive(const uv_loop_t* loop) | 如果有被引用的活动句柄、活动请求或者循环里的关闭句柄时返回非零值,否则返回零值,表示事件不再活动 |
| uv__io_t | IO观察者,是一个结构体,描述了上层事件和事件回调信息 |
| uv__io_poll(loop, timeout) | 把新增需要被监听的fd放到poll中,其内部有一个epoll_wait方法 |
| uv_async_start、uv__io_start | 注册IO观察者到事件loop里,并注册需要监听的事件 |
| uv__async_send、uv_async_send | 触发事件执行,并执行事件的回调 |
在Native侧调用ArkTS侧的系统能力,除了使用线程安全函数外,还可以直接使用libuv,但需要额外编译libuv源码,如果需要了解更多libuv的知识,可以参见(https://github.com/libuv/libuv)。
Mike98
十年以上软件开发经验,近两年积极拥抱鸿蒙生态,主导多款鸿蒙app的研发工作,欢迎一起交流
帖子
鸿蒙如何在Native调用ArkTS方法
2025-11-21 15:03:31 发布