赞
踩
N-API 调用时底层 VM 的堆中对象会返回 napi_value 句柄。函数代码运行时,这些句柄对象一直保持活跃;待函数结束时,才会被 GC 回收。 N-API 对象的生命周期管理本质上是控制对象什么时机被销毁。主要通过添加作用域和 create reference 方式。
在函数执行结束前,提前销毁这个 NAPI 对象;使用 napi_open/close__handle_scope 在函数创建作用域,从该作用域跳出后,里面的变量被销毁。
- Row() {
- Text("handleScope")
- .fontSize(50)
- .fontWeight(FontWeight.Bold)
- .onClick(() => {
- hilog.info(0x0000,
- 'testTag',
- 'Test NAPI handleScope %{public}d',
- // 调用 C++ 侧方法,传入数组
- testNapi.handleScope([1,2,3,4,5,6])
- );
- })
- }
- static napi_value handleScope(napi_env env, napi_callback_info info)
- {
- size_t argc = 1;
- napi_value object;
- // 接收 JS 侧传入的数组,赋值给 object。
- napi_get_cb_info(env, info, &argc, &object, nullptr, nullptr);
-
- napi_handle_scope scope;
- // 创建一个新的作用域,赋值给 scope,这里是作用域的起点。
- napi_open_handle_scope(env, &scope);
-
- // 在作用域里定义 NAPI 对象
- napi_value eleVal;
- // 用数组的元素给对象赋值
- napi_get_element(env, object, 2, &eleVal);
-
- // 关闭 scope 作用域,此处为作用域终点
- napi_close_handle_scope(env, scope);
-
- // 作用域外,是访问不了作用域内的数据,比如 eleVal
- int32_t res;
- napi_get_value_int32(env, eleVal, &res);
- // eleVal 打印结果是 0,而不是 2,说明 eleVal 在函数结束前被销毁。
- // 去除作用域,打印结果是 2
- return eleVal;
- }
使用 napi_open/close_escapable_handle_scope,如其名 escapable 可逃逸的,这种作用域里的变量是可逃逸到外部作用域,但是需要 napi_escape_handle 指定哪个对象。
- Row() {
- Text("handleEscapableScope")
- .fontSize(50)
- .fontWeight(FontWeight.Bold)
- .onClick(() => {
- hilog.info(0x0000,
- 'testTag',
- 'Test NAPI handleEscapableScope %{public}d',
- // 调用 C++ 侧方法,传入数组
- testNapi.handleEscapableScope([1,2,3,4,5,6])
- );
- })
- }
- static napi_value handleEscapableScope(napi_env env, napi_callback_info info)
- {
- size_t argc = 1;
- napi_value object;
- // 接收 JS 侧传入的数组,赋值给 object。
- napi_get_cb_info(env, info, &argc, &object, nullptr, nullptr);
-
- napi_value outerEleVal;
-
- napi_escapable_handle_scope scope;
- // 创建一个新的可逃逸作用域,赋值给 scope,这里是作用域的起点。
- napi_open_escapable_handle_scope(env, &scope);
- // 在作用域里定义将要逃逸的 NAPI 对象
- napi_value eleVal;
- // 用数组的元素给对象赋值
- napi_get_element(env, object, 2, &eleVal);
- // 将 eleVal 逃逸出作用域,外部用 outerEleVal 接收
- napi_escape_handle(env, scope, eleVal, &outerEleVal);
- // 关闭 scope 作用域,此处为作用域终点
- napi_close_escapable_handle_scope(env, scope);
-
- int32_t res;
- napi_get_value_int32(env, outerEleVal, &res);
- // outerEleVal 打印的结果是 2,说明指定的 NAPI 对象 eleVal,已逃逸出作用域
- return outerEleVal;
- }
引用计数垃圾收集策略 给函数里的 NAPI 对象创建 reference,通过控制 reference 的引用计数不为 0,让该对象不被回收销毁
- Row() {
- Text("handleReference")
- .fontSize(50)
- .fontWeight(FontWeight.Bold)
- .onClick(() => {
- hilog.info(0x0000,
- 'testTag',
- 'Test NAPI handleReference %{public}d',
- // 调用 C++ 侧方法
- testNapi.handleReference()
- );
- })
- }
- // 定义引用
- napi_ref ref;
-
- // 使用异步 work,是为了模拟主函数结束后,在异步函数里去访问对象
- // 验证主函数的 NAPI 对象是否随主函数结束而被销毁
- struct AsyncWorkInfo {
- napi_async_work work;
- };
-
- struct AsyncWorkInfo data = { nullptr };
-
- static void AExecute(napi_env env, void *data) {
- // 异步函数内
- struct AsyncWorkInfo *arg = (struct AsyncWorkInfo *)data;
- napi_value recv;
- // 获取引用值,用 recv 接收
- napi_get_reference_value(env, ref, &recv);
-
- int32_t res;
- napi_get_value_int32(env, recv, &res);
- // 打印引用值为 333,说明该引用映射的主函数 NAPI 对象没有随着主函数结束被销毁
- // 从而控制了 NAPI 对象的生命周期
- OH_LOG_INFO(LOG_APP, "ref val is %{pubilc}d", res);
- }
-
-
- static napi_value handleReference(napi_env env, napi_callback_info info)
- {
- // 主函数内
- napi_value resourceName;
- napi_create_string_utf8(env, "asyncWork", NAPI_AUTO_LENGTH, &resourceName);
-
- // 定义主函数的 NAPI 对象
- napi_value test_data;
- napi_create_int32(env, 333, &test_data);
-
- // 给主函数 NAPI 创建绑定引用
- napi_create_reference(env, test_data, 1, &ref);
-
- struct AsyncWorkInfo *ptr = &data;
- // 异步执行 AExecute
- napi_create_async_work(env, nullptr, resourceName, AExecute, nullptr, ptr, &ptr->work);
- napi_queue_async_work(env, ptr->work);
- return resourceName;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。