1、Sendable对象的序列化与反序列化
Sendable对象的简单介绍参考文章:鸿蒙多线程开发——线程间数据通信对象03(sendable)
与JSON对象的序列化和反序列化类似,Sendable对象的序列化和反序列化是通过ArkTs提供的ASON工具来完成。
与JSON类似,我们可以通过ASON.stringify方法将对象转换成字符串,也可以通过ASON.parse方法将字符串转成Sendable对象,以便此对象在并发任务间进行高性能引用传递。
需要注意的是:
ASON.parse默认生成的Sendable对象不支持增删属性。如果需要支持返回对象的布局可变,可以指定返回类型为MAP,此时会全部返回collections.Map对象,支持增删属性。
一个序列化(ASON.stringify)使用示例如下:
import { ArkTSUtils, collections } from '@kit.ArkTS';
// ...
let arr = new collections.Array(1, 2, 3);
let str = ArkTSUtils.ASON.stringify(arr);
console.info(str); // 期望输出: '[1,2,3]'
一个反序列化(ASON.parse)使用示例如下:
import { lang } from '@kit.ArkTS';
import { ArkTSUtils, collections } from '@kit.ArkTS';
type ISendable = lang.ISendable;
let jsonText = '{"name": "John", "age": 30, "city": "ChongQing"}';
let obj = ArkTSUtils.ASON.parse(jsonText) as ISendable;
console.info((obj as object)?.["name"]); // 输出: 'John'
console.info((obj as object)?.["age"]); // 输出: 30
console.info((obj as object)?.["city"]); // 输出: 'ChongQing'
反序列化时,也可以额外传入Option字段,示例如下:
import { lang } from '@kit.ArkTS';
import { ArkTSUtils, collections } from '@kit.ArkTS';
type ISendable = lang.ISendable;
let options: ArkTSUtils.ASON.ParseOptions = {
bigIntMode: ArkTSUtils.ASON.BigIntMode.PARSE_AS_BIGINT,
parseReturnType: ArkTSUtils.ASON.ParseReturnType.OBJECT,
}
let numberText = '{"largeNumber":112233445566778899}';
let numberObj = ArkTSUtils.ASON.parse(numberText,undefined,options) as ISendable;
console.info((numberObj as object)?.["largeNumber"]);
// 期望输出: 112233445566778899
ASON工具提供了的两个序列化和反序列化接口,定义如下:
// 序列化ISendable对象
stringify(value: ISendable | null | undefined): string
// 反序列化ISendable对象
parse(text: string, reviver?: Transformer, options?: ParseOptions): ISendable | null
parse函数还有两个可选参数:reviver、options。含义与定义介绍如下:
-
reviver?: Transformer
转换函数,传入该参数,可以用来修改解析生成的原始值。默认值是undefined。(目前只支持传入undefined)。Transformer类型定义如下:
// this:在解析的键值对所属的对象。key:属性名。value: 在解析的键值对d的值
type Transformer = (this: ISendable, key: string, value: ISendable | undefined | null) => ISendable | undefined | null
-
options?: ParseOptions
解析的配置,传入该参数,可以用来控制解析生成的结果类型。默认值是undefined。ParseOptions类型定义如下:
struct ParseOptions {
bigIntMode: BigIntMode; // 定义处理BigInt的模式。
parseReturnType: ParseReturnType; // 定义解析结果的返回类型。
}
// 定义处理BigInt的模式枚举
enum BigIntMode {
DEFAULT = 0; // 不支持BigInt。
PARSE_AS_BIGINT = 1; // 当整数小于-(2^53-1)或大于(2^53-1)时,解析为BigInt。
ALWAYS_PARSE_AS_BIGINT = 2; // 所有整数都解析为BigInt。
}
enum ParseReturnType {
OBJECT = 0; // 返回Sendable Object对象。
}
2、Sendable对象冻结
Sendable对象支持冻结操作,冻结后的对象变成只读对象,不能增删改属性,因此在多个并发实例间访问均不需要加锁,可以通过调用Object.freeze接口冻结对象。
使用示例如下:
👉🏻 step 1: 供ts文件封装Object.freeze方法。
// helper.ts
export function freezeObj(obj: any) {
Object.freeze(obj);
}
👉🏻 step 2: 通过调用freeze方法冻结对象,并将对象发送给子线程。
// Index.ets
import { freezeObj } from './helper';
import { worker } from '@kit.ArkTS';
@Sendable
export class GlobalConfig {
// 一些配置属性与方法
init() {
// 初始化相关逻辑
freezeObj(this); // 初始化完成后冻结当前对象
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Text("Sendable freezeObj Test")
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
let gConifg = new GlobalConfig();
gConifg.init();
const workerInstance = new worker.ThreadWorker('entry/ets/workers/Worker.ets', { name: "Worker1" });
workerInstance.postMessage(gConifg);
})
}
.height('100%')
.width('100%')
}
}
👉🏻 step 3: 子线程不加锁直接操作对象。
// Worker.ets
import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS';
import { GlobalConfig } from '../pages/Index';
const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
workerPort.onmessage = (e: MessageEvents) => {
let gConfig: GlobalConfig = e.data;
// 使用gConfig对象
}