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 114```ts 115// Index.ets 116import { taskpool, ArkTSUtils } from '@kit.ArkTS'; 117import { SendableTestClass, ISendable } from './sendable'; 118 119// 在并发函数中模拟数据处理 120@Concurrent 121async function taskFunc(sendableObj: SendableTestClass) { 122 console.info("SendableTestClass: name is: " + sendableObj.printName() + ", age is: " + sendableObj.printAge() + ", sex is: " + sendableObj.printSex()); 123 sendableObj.setAge(28); 124 console.info("SendableTestClass: age is: " + sendableObj.printAge()); 125 126 // 解析sendableObj.arr数据生成JSON字符串 127 let str = ArkTSUtils.ASON.stringify(sendableObj.arr); 128 console.info("SendableTestClass: str is: " + str); 129 130 // 解析该数据并生成ISendable数据 131 let jsonStr = '{"name": "Alexa", "age": 23, "sex": "female"}'; 132 let obj = ArkTSUtils.ASON.parse(jsonStr) as ISendable; 133 console.info("SendableTestClass: type is: " + typeof obj); 134 console.info("SendableTestClass: name is: " + (obj as object)?.["name"]); // 输出: 'Alexa' 135 console.info("SendableTestClass: age is: " + (obj as object)?.["age"]); // 输出: 23 136 console.info("SendableTestClass: sex is: " + (obj as object)?.["sex"]); // 输出: 'female' 137} 138async function test() { 139 // 使用taskpool传递数据 140 let obj: SendableTestClass = new SendableTestClass(); 141 let task: taskpool.Task = new taskpool.Task(taskFunc, obj); 142 await taskpool.execute(task); 143} 144 145@Entry 146@Component 147struct Index { 148 @State message: string = 'Hello World'; 149 150 build() { 151 RelativeContainer() { 152 Text(this.message) 153 .id('HelloWorld') 154 .fontSize(50) 155 .fontWeight(FontWeight.Bold) 156 .alignRules({ 157 center: { anchor: '__container__', align: VerticalAlign.Center }, 158 middle: { anchor: '__container__', align: HorizontalAlign.Center } 159 }) 160 .onClick(() => { 161 test(); 162 }) 163 } 164 .height('100%') 165 .width('100%') 166 } 167} 168``` 169 170```ts 171// sendable.ets 172// 定义模拟类Test,模仿开发过程中需传递带方法的class 173import { lang, collections } from '@kit.ArkTS' 174 175export type ISendable = lang.ISendable; 176 177@Sendable 178export class SendableTestClass { 179 name: string = 'John'; 180 age: number = 20; 181 sex: string = "man"; 182 arr: collections.Array<number> = new collections.Array<number>(1, 2, 3); 183 constructor() { 184 } 185 setAge(age: number) : void { 186 this.age = age; 187 } 188 189 printName(): string { 190 return this.name; 191 } 192 193 printAge(): number { 194 return this.age; 195 } 196 197 printSex(): string { 198 return this.sex; 199 } 200} 201```