“持久化”不等于“原样存回来”

截图整理工具的设置页有几个用户偏好:默认分类、是否开启自动打码、特征向量模型版本、上次导入的游标位置。用 PersistenceV2.connect 存进去,开发阶段一切正常,杀掉进程重进,一半字段是 undefined,甚至整个 connect 返回了 undefined。

两个独立的问题撞在一起了。connect 返回 undefined,是因为冷启动时 key 里还没有数据,必须带上默认值构造器。字段在重启后丢失,是因为 PersistenceV2 的序列化有严格的类型边界:类必须可序列化,带方法、Map、Set 的字段存不进去,复杂类型的属性信息在反序列化时可能丢失。

defaultCreator 是安全入口,@Type 是类型保留的钥匙

PersistenceV2.connect 的第三个参数 defaultCreator 在磁盘没有数据时提供默认实例,保证返回值不会是 undefined。另一个容易被忽略的点是嵌套类属性的类型标注。如果设置类里有一个 vectorConfig: VectorConfig 这样的嵌套对象,反序列化之后 vectorConfig 可能变成普通对象,丢失类方法或类型信息。@Type 装饰器就是用来标记属性原始类型的,确保复杂类型在序列化和反序列化过程中不丢失。

typescript

@ObservedV2
class VectorConfig {
  @Trace modelVersion: string = 'v1.0';
  @Trace dimension: number = 512;
}

@ObservedV2
class AppSettings {
  @Trace defaultCategory: string = 'all';
  @Trace autoMosaic: boolean = false;
  @Trace importCursor: number = 0;
  @Type(VectorConfig)           // 反序列化时保留类型
  @Trace vectorConfig: VectorConfig = new VectorConfig();
}

const settings = PersistenceV2.connect(
  AppSettings,
  'app_settings',
  () => new AppSettings()      // 磁盘无数据时走这里
);

@Type(VectorConfig) 必须和 @Trace 同时存在。@Trace 负责运行时属性变化的观测,@Type 负责序列化时类型信息的保留。两者管的是不同的链路,缺一个都会在特定场景下出问题。defaultCreator 返回的实例要带完整的默认字段,不能是一个空壳对象,否则迁移逻辑会因为字段缺失而误判。

旧版本升级不走构造函数,迁移必须显式做

defaultCreator 解决的是“磁盘上什么都没有”的场景。从旧版本升级上来是另一种情况:磁盘上有序列化过的 JSON,PersistenceV2 把它反序列化成对象,但不会走类的构造函数。新版本新增的字段,旧 JSON 里没有,拿到手就是 undefined。

迁移应该放在 connect 返回之后、UI 使用之前,集中做一次字段补全。不要依赖 @Trace 的默认值在反序列化路径上生效,那条路径不走构造函数。

typescript

function migrateSettings(s: AppSettings): void {
  if (s.autoMosaic === undefined) s.autoMosaic = false;
  if (s.importCursor === undefined) s.importCursor = 0;
  if (!s.vectorConfig) s.vectorConfig = new VectorConfig();
}

只放可序列化的数据,业务逻辑不要塞进持久化类

PersistenceV2 的定位是“可序列化的状态快照”,不是“带行为的业务对象”。持久化类里只放基础类型和可被 @Type 标注的嵌套类,方法、Map、Set、闭包一律不要放。如果你需要缓存特征向量,向量本身用 number[] 或 ArrayBuffer 存进 relationalStore,AppSettings 里只保留一个模型版本号或游标位置。

连接之后还要检查 PersistenceV2.notifyOnError,序列化失败时不一定会抛到你的业务代码里,注册错误监听能在开发阶段把问题暴露出来。持久化的验收标准不是“写进去了”,是“杀掉进程、升级覆盖、清数据重装三种情况下,读出来的每一个字段都符合预期”。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐