当前位置: 首页 > article >正文

鸿蒙多线程开发——Sendable使用注意事项

1、概 述

本文是在鸿蒙多线程开发——线程间数据通信对象03(sendable)基础上做的扩展讨论。

Sendable协议定义了ArkTS的可共享对象体系及其规格约束。符合Sendable协议的数据(以下简称Sendable对象)可以在ArkTS并发实例间传递。

默认情况下,Sendable数据在ArkTS并发实例间(包括主线程、TaskPool、Worker线程)传递的行为是引用传递。同时,ArkTS也支持Sendable数据在ArkTS并发实例间拷贝传递。

Sendable的使用有一些需要注意的事项,本文针对较常见的情况做讨论。

2、Sendable的使用规则与约束

主要规则有:

  • Sendable class只能继承自Sendable class;

  • 非Sendable class只能继承自非Sendable class;

  • 非Sendable class只能实现非Sendable interface;

  • Sendable class/interface成员变量必须是Sendable支持的数据类型;

  • Sendable class/interface的成员变量不支持使用!断言;

  • Sendable class/interface的成员变量不支持使用计算属性名;

  • 泛型类中的Sendable class,collections.Array,collections.Map,collections.Set的模板类型必须是Sendable类型;

  • Sendable class的内部不允许使用当前模块内上下文环境中定义的变量;

  • Sendable class和Sendable function不能使用除了@Sendable的其它装饰器;

  • 不能使用对象字面量/数组字面量初始化Sendable类型;

  • 非Sendable类型不可以as成Sendable类型;

  • 箭头函数不支持共享;

  • Sendable装饰器修饰类型时仅支持修饰函数类型;

展开说明如下:

👉🏻 Sendable class只能继承自Sendable class

✅ 正确使用案例:

@Sendableclass A {  constructor() {  }}@Sendableclass B extends A {  constructor() {    super()  }}

❌ 错误使用案例:​​​​​​​

class A {  constructor() {  }}@Sendableclass B extends A {  constructor() {    super()  }}

👉🏻 非Sendable class只能继承自非Sendable class

✅ 正确使用案例:​​​​​​​

class A {  constructor() {  }}class B extends A {  constructor() {    super()  }}

❌ 错误使用案例:​​​​​​

@Sendableclass A {  constructor() {  }}class B extends A {  constructor() {    super()  }}

👉🏻 非Sendable class只能实现非Sendable interface

✅ 正确使用案例:​​​​​​​

interface I {};class B implements I {};

❌ 错误使用案例:​​​​​​​

import { lang } from '@kit.ArkTS';type ISendable = lang.ISendable;interface I extends ISendable {};class B implements I {};

👉🏻 Sendable class/interface成员变量必须是Sendable支持的数据类型

✅ 正确使用案例:​​​​​​​

@Sendableclass A {  constructor() {  }  a: number = 0;}

❌ 错误使用案例:​​​​​​​

@Sendableclass A {  constructor() {  }  b: Array<number> = [1, 2, 3] // 需使用collections.Array}

👉🏻 Sendable class/interface的成员变量不支持使用!断言

✅ 正确使用案例:​​​​​​​

@Sendableclass A {  constructor() {  }  a: number = 0;}

❌ 错误使用案例:​​​​​​​

@Sendableclass A {  constructor() {  }  a!: number;}

👉🏻 Sendable class/interface的成员变量不支持使用计算属性名

✅ 正确使用案例:​​​​​​​

@Sendableclass A {    num1: number = 1;    num2: number = 2;    add(): number {      return this.num1 + this.num2;    }}

❌ 错误使用案例:​​​​​​​

enum B {    b1 = "bbb"}@Sendableclass A {    ["aaa"]: number = 1; // ["aaa"] is allowed in other classes in ets files    [B.b1]: number = 2; // [B.b1] is allowed in other classes in ets files}

👉🏻 泛型类中的Sendable class,collections.Array,collections.Map,collections.Set的模板类型必须是Sendable类型

✅ 正确使用案例:​​​​​​​

import { collections } from '@kit.ArkTS';try {  let arr1: collections.Array<number> = new collections.Array<number>();  let num: number = 1;  arr1.push(num);} catch (e) {  console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);}

❌ 错误使用案例:​​​​​​​

import { collections } from '@kit.ArkTS';try {  let arr1: collections.Array<Array<number>> = new collections.Array<Array<number>>();  let arr2: Array<number> = new Array<number>();  arr2.push(1);  arr1.push(arr2);} catch (e) {  console.error(`taskpool execute: Code: ${e.code}, message: ${e.message}`);}

👉🏻 Sendable class的内部不允许使用当前模块内上下文环境中定义的变量

由于Sendable对象在不同并发实例间的上下文环境不同,如果直接访问会有非预期行为。不支持Sendable对象使用当前模块内上下文环境中定义的变量,如果违反,编译阶段会报错。

✅ 正确使用案例:​​​​​​​

import { lang } from '@kit.ArkTS';type ISendable = lang.ISendable;interface I extends ISendable {}@Sendableclass B implements I {  static o: number = 1;  static bar(): B {    return new B();  }}@Sendableclass C {  v: I = new B();  u: number = B.o;  foo() {    return B.bar();  }}

❌ 错误使用案例:​​​​​​​

import { lang } from '@kit.ArkTS';type ISendable = lang.ISendable;interface I extends ISendable {}@Sendableclass B implements I {}function bar(): B {  return new B();}let b = new B();{  @Sendable  class A implements I {}  @Sendable  class C {    u: I = bar(); // bar不是sendable class对象,编译报错    v: I = new A(); // A不是定义在top level中,编译报错    foo() {      return b; // b不是sendable class对象,而是sendable class的实例,编译报错    }  }}

👉🏻 Sendable class和Sendable function不能使用除了@Sendable的其它装饰器

如果类装饰器定义在ts文件中,产生修改类的布局的行为,那么会造成运行时的错误。

✅ 正确使用案例:​​​​​​​

@Sendableclass A {  num: number = 1;}

❌ 错误使用案例:​​​​​​​

@Sendable@Observedclass C {  num: number = 1;}

👉🏻 不能使用对象字面量/数组字面量初始化Sendable类型

Sendable数据类型只能通过Sendable类型的new表达式创建。

✅ 正确使用案例:​​​​​​​

import { collections } from '@kit.ArkTS';let arr1: collections.Array<number> = new collections.Array<number>(1, 2, 3); // 是Sendable类型

❌ 错误使用案例:​​​​​​​

import { collections } from '@kit.ArkTS';let arr2: collections.Array<number> = [1, 2, 3]; // 不是Sendable类型,编译报错let arr3: number[] = [1, 2, 3]; // 不是Sendable类型,正例,不报错let arr4: number[] = new collections.Array<number>(1, 2, 3); // 编译报错

👉🏻 非Sendable类型不可以as成Sendable类型

✅ 正确使用案例:​​​​​​​

class A {  state: number = 0;}@Sendableclass SendableA {  state: number = 0;}let a1: A = new SendableA() as A;

❌ 错误使用案例:​​​​​​​

class A {  state: number = 0;}@Sendableclass SendableA {  state: number = 0;}let a2: SendableA = new A() as SendableA;

👉🏻 箭头函数不支持共享

✅ 正确使用案例:​​​​​​​

@Sendabletype SendableFuncType = () => void;@Sendablefunction SendableFunc() {  console.info("Sendable func");}@Sendableclass SendableClass {  constructor(f: SendableFuncType) {    this.func = f;  }  func: SendableFuncType;}let sendableClass = new SendableClass(SendableFunc);

❌ 错误使用案例:​​​​​​​

@Sendabletype SendableFuncType = () => void;let func: SendableFuncType = () => {}; // 编译报错@Sendableclass SendableClass {  func: SendableFuncType = () => {}; // 编译报错}

👉🏻 Sendable装饰器修饰类型时仅支持修饰函数类型

Sendable装饰器修饰类型时仅支持修饰函数类型。

✅ 正确使用案例:​​​​​​​

@Sendabletype SendableFuncType = () => void;

❌ 错误使用案例:​​​​​​​

@Sendabletype A = number; // 编译报错@Sendableclass C {}@Sendabletype D = C; // 编译报错

3、HAR中使用Sendable

在HAR中使用Sendable时,需开启编译生成TS文件的配置。

修改方式:在HAR模块下的module.json5文件中将"metadata"字段下的"name"设置为“UseTsHar”,配置如下所示:​​​​​​​

{  "module": {    "name": "TsClosedHar",    "type": "har",    "deviceTypes": [      "default",      "tablet",      "2in1"    ],    "metadata": [      {        "name": "UseTsHar",        "value": "true"      }    ]  }}

4、与TS/JS交互的规则

4.1、ArkTS通用规则(目前只针对Sendable对象)

  • Sendable对象传入TS/JS的接口中,禁止操作其对象布局(增、删属性,改变属性类型)。

  • Sendable对象设置到TS/JS的对象上,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。

  • Sendable对象放入TS/JS的容器中,TS中获取到这个Sendable对象后,禁止操作其对象布局(增、删属性,改变属性类型)。

4.2、NAPI规则(目前只针对Sendable对象)

  • 禁止删除属性,不能使用的接口有:napi_delete_property。

  • 禁止新增属性,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。

  • 禁止修改属性类型,不能使用的接口有:napi_set_property、napi_set_named_property、napi_define_properties。

  • 不支持Symbol相关接口和类型,不能使用的接口有:napi_create_symbol、napi_is_symbol_object、napi_symbol。

5、与UI交互的规则

Sendable数据需要与makeObserved联用,才可以观察Sendable对象的数据变化。


http://www.kler.cn/a/421466.html

相关文章:

  • WordPress ElementorPageBuilder插件 任意文件读取漏洞复现(CVE-2024-9935)
  • 【最新免费PPT制作并下载】Kimi PPT助手:智能化演示文稿生成,职场效率的革命性提升
  • 【AI日记】24.12.03 kaggle 比赛 Titanic-6
  • JavaScript(JS)的对象
  • LeetCode 64. 最小路径和(HOT100)
  • Android 应用单元测试涉及 Telephony 环境初始化问题
  • 【docker】docker compose多容器部署
  • Rain后台权限管理系统,快速开发
  • 我的知识图谱和Neo4j数据库的使用
  • AI×5G 市场前瞻及应用现状
  • 深入探索 HarmonyOS 的 Navigation 组件:灵活的页面管理与动态导航
  • win10-Docker打不开this can prevent Docker from starting. Use at your own risk.
  • 【C++】LeetCode:LCR 022. 环形链表 II
  • 数字图像处理(13):图像裁剪
  • 银河麒麟V10-SP1设置redis开机自启
  • Web安全基础实践
  • 论文阅读:Single-cell transcriptomics of 20 mouse organs creates a Tabula Muris
  • 【docker】Overlay网络
  • 【分页查询】.NET开源 ORM 框架 SqlSugar 系列
  • ceph的用户管理和cephx认证
  • 代理动态代理
  • Web开发基础学习——HTML, CSS, JavaScript 的区别和联系
  • Java 整合图片处理相关一套:传输、保存、重命名、删除、AI图片文字识别、图片映射、vue3裁剪、设置黑白色、设置负片、提高照片品质
  • 【版本控制】SVN安装到使用一条路讲解
  • 全球【风电叶片专用环氧树脂】市场集中度较高,环氧树脂主要产地在中国、欧洲和美国
  • PyTorch 2.5.1: Bugs修复版发布