• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Sendable使用场景
2Sendable对象可在不同并发实例间通过引用传递,相比序列化方式更高效,同时不会丢失class上携带的成员方法。因此,Sendable可以解决两个关键场景的问题:
3
4- 跨并发实例传输大数据(例如达到100KB以上的数据)。
5
6- 跨并发实例传递带方法的class实例对象。
7
8## 跨并发实例传输大数据场景
9
10由于跨并发实例序列化的开销随数据量线性增长,因此当传输数据量较大时(100KB的数据传输耗时约为1ms),跨并发实例的拷贝开销会影响应用性能。使用引用传递方式传输对象可提升性能。
11
12**示例:**
13
14```ts
15// Index.ets
16import { taskpool } from '@kit.ArkTS';
17import { testTypeA, testTypeB, Test } from './sendable';
18import { BusinessError, emitter } from '@kit.BasicServicesKit';
19
20// 在并发函数中模拟数据处理
21@Concurrent
22async function taskFunc(obj: Test) {
23  console.info("test task res1 is: " + obj.data1.name + " res2 is: " + obj.data2.name);
24}
25
26async function test() {
27  // 使用taskpool传递数据
28  let a: testTypeA = new testTypeA("testTypeA");
29  let b: testTypeB = new testTypeB("testTypeB");
30  let obj: Test = new Test(a, b);
31  let task: taskpool.Task = new taskpool.Task(taskFunc, obj);
32  await taskpool.execute(task);
33}
34
35@Concurrent
36function SensorListener() {
37  // 监听逻辑
38  // ...
39}
40
41@Entry
42@Component
43struct Index {
44  build() {
45    Column() {
46      Text("Listener task")
47        .id('HelloWorld')
48        .fontSize(50)
49        .fontWeight(FontWeight.Bold)
50        .onClick(() => {
51          let sensorTask = new taskpool.LongTask(SensorListener);
52          emitter.on({ eventId: 0 }, (data) => {
53            // Do something here
54            console.info(`Receive ACCELEROMETER data: {${data.data?.x}, ${data.data?.y}, ${data.data?.z}`);
55          });
56          taskpool.execute(sensorTask).then(() => {
57            console.info("Add listener of ACCELEROMETER success");
58          }).catch((e: BusinessError) => {
59            // Process error
60          })
61        })
62      Text("Data processing task")
63        .id('HelloWorld')
64        .fontSize(50)
65        .fontWeight(FontWeight.Bold)
66        .onClick(() => {
67          test();
68        })
69    }
70    .height('100%')
71    .width('100%')
72  }
73}
74```
75
76```ts
77// sendable.ets
78// 将数据量较大的数据在Sendable class中组装
79@Sendable
80export class testTypeA {
81  name: string = "A";
82  constructor(name: string) {
83    this.name = name;
84  }
85}
86
87@Sendable
88export class testTypeB {
89  name: string = "B";
90  constructor(name: string) {
91    this.name = name;
92  }
93}
94
95@Sendable
96export class Test {
97  data1: testTypeA;
98  data2: testTypeB;
99  constructor(arg1: testTypeA, arg2: testTypeB) {
100    this.data1 = arg1;
101    this.data2 = arg2;
102  }
103}
104```
105
106
107## 跨并发实例传递带方法的class实例对象
108
109由于序列化传输实例对象时会丢失方法,因此在需要调用实例方法时,需使用引用传递方式。在数据处理过程中有需要解析的数据,可使用[ASON工具](ason-parsing-generation.md)解析。
110
111**示例:**
112
113```ts
114// Index.ets
115import { taskpool, ArkTSUtils } from '@kit.ArkTS';
116import { SendableTestClass, ISendable } from './sendable';
117
118// 在并发函数中模拟数据处理
119@Concurrent
120async function taskFunc(sendableObj: SendableTestClass) {
121  console.info("SendableTestClass: name is: " + sendableObj.printName() + ", age is: " + sendableObj.printAge() + ", sex is: " + sendableObj.printSex());
122  sendableObj.setAge(28);
123  console.info("SendableTestClass: age is: " + sendableObj.printAge());
124
125  // 解析sendableObj.arr数据生成JSON字符串
126  let str = ArkTSUtils.ASON.stringify(sendableObj.arr);
127  console.info("SendableTestClass: str is: " + str);
128
129  // 解析该数据并生成ISendable数据
130  let jsonStr = '{"name": "Alexa", "age": 23, "sex": "female"}';
131  let obj = ArkTSUtils.ASON.parse(jsonStr) as ISendable;
132  console.info("SendableTestClass: type is: " + typeof obj);
133  console.info("SendableTestClass: name is: " + (obj as object)?.["name"]); // 输出: 'Alexa'
134  console.info("SendableTestClass: age is: " + (obj as object)?.["age"]); // 输出: 23
135  console.info("SendableTestClass: sex is: " + (obj as object)?.["sex"]); // 输出: 'female'
136}
137async function test() {
138  // 使用taskpool传递数据
139  let obj: SendableTestClass = new SendableTestClass();
140  let task: taskpool.Task = new taskpool.Task(taskFunc, obj);
141  await taskpool.execute(task);
142}
143
144@Entry
145@Component
146struct Index {
147  @State message: string = 'Hello World';
148
149  build() {
150    RelativeContainer() {
151      Text(this.message)
152        .id('HelloWorld')
153        .fontSize(50)
154        .fontWeight(FontWeight.Bold)
155        .alignRules({
156          center: { anchor: '__container__', align: VerticalAlign.Center },
157          middle: { anchor: '__container__', align: HorizontalAlign.Center }
158        })
159        .onClick(() => {
160          test();
161        })
162    }
163    .height('100%')
164    .width('100%')
165  }
166}
167```
168
169```ts
170// sendable.ets
171// 定义模拟类Test,模仿开发过程中需传递带方法的class
172import { lang, collections } from '@kit.ArkTS'
173
174export type ISendable = lang.ISendable;
175
176@Sendable
177export class SendableTestClass {
178  name: string = 'John';
179  age: number = 20;
180  sex: string = "man";
181  arr: collections.Array<number> = new collections.Array<number>(1, 2, 3);
182  constructor() {
183  }
184  setAge(age: number) : void {
185    this.age = age;
186  }
187
188  printName(): string {
189    return this.name;
190  }
191
192  printAge(): number {
193    return this.age;
194  }
195
196  printSex(): string {
197    return this.sex;
198  }
199}
200```