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```