HarmonyOS Preferences 配置治理:键名设计、版本迁移与提交边界

实际项目里,Preferences 常被当成随手可写的配置盒子:页面直接拼键名、写完忘记 flush、版本升级后旧字段没人迁移。短期看没问题,等用户升级、灰度回滚或多页面同时读写时,配置状态就会变得不可解释。本文用应用设置中心场景,把键名、默认值、迁移、提交和观察者拆成可维护链路。

请添加图片描述

本文先把配置混乱点讲清

这篇文章重点不是演示一个 put,而是让配置数据具备可读、可迁移、可排查的工程边界。

  • 键名集中管理,禁止页面散落拼接。
  • 读取入口提供类型化默认值。
  • 升级时按 schemaVersion 做迁移。
  • 写入后明确 flush,避免只停留在内存。

Preferences 资料与声明入口

项目 内容
本地声明 D:/harmonyos/SDK/23/ets/api/@ohos.data.preferences.d.ts
核心 API getPreferences、put、get、delete、flush、on/off change。
适用数据 轻量配置、开关、最近选择项,不适合大对象和强关系数据。
缓存边界 实例会驻留内存,需要按生命周期释放引用。

配置存储的版本边界

项目 内容
SDK HarmonyOS SDK 23。
场景 路线应用设置、地图偏好、首页开关。
不覆盖 账号敏感令牌加密,请配合 HUKS。
一致性 写入后 flush,读取时提供默认值。

请添加图片描述

请添加图片描述

键名先集中,不让页面自由发挥

键名散落后,删除和迁移都会变成全文搜索。先建立 SettingsKeys,所有页面只能引用常量。

export const SettingsKeys = {
  SCHEMA_VERSION: 'settings.schema.version',
  MAP_LAYER: 'settings.map.layer',
  AUTO_SYNC: 'settings.auto.sync',
  LAST_ROUTE_CITY: 'settings.last.route.city'
} as const;

export type SettingKey = typeof SettingsKeys[keyof typeof SettingsKeys];

这段代码拥有配置协议边界。页面不拼字符串,迁移函数也能明确知道每个键的含义。

获取实例要由仓储层托管

Preferences 实例不应该被每个页面重复获取。仓储层持有实例,并在初始化阶段完成一次加载。

import preferences from '@ohos.data.preferences';
import common from '@ohos.app.ability.common';

export class SettingsStore {
  private pref?: preferences.Preferences;

  async open(context: common.UIAbilityContext): Promise<void> {
    this.pref = await preferences.getPreferences(context, 'trail_settings');
    await this.migrateIfNeeded();
  }

  private ensure(): preferences.Preferences {
    if (!this.pref) {
      throw new Error('SettingsStore is not opened');
    }
    return this.pref;
  }
}

仓储层负责打开和校验实例。页面只调用业务方法,不直接接触文件名和底层对象。

读取时给出类型化默认值

配置缺失不应该让页面判断 undefined。读取入口直接返回业务可用值,并把类型转换放在仓储层。

async getMapLayer(): Promise<'standard' | 'satellite'> {
  const value = await this.ensure().get(SettingsKeys.MAP_LAYER, 'standard');
  return value === 'satellite' ? 'satellite' : 'standard';
}

async isAutoSyncEnabled(): Promise<boolean> {
  const value = await this.ensure().get(SettingsKeys.AUTO_SYNC, true);
  return value === true;
}

读取代码承担默认值和类型收口。页面拿到的已经是业务类型,不再重复判断存储细节。

写入必须跟提交策略绑定

只 put 不 flush,用户立刻杀进程时可能丢失配置。对于设置页的显式保存,写完后应立即 flush。

async saveMapPreference(layer: 'standard' | 'satellite', autoSync: boolean): Promise<void> {
  const pref = this.ensure();
  await pref.put(SettingsKeys.MAP_LAYER, layer);
  await pref.put(SettingsKeys.AUTO_SYNC, autoSync);
  await pref.flush();
}

保存方法是事务感最强的业务边界。它把多个配置写入和落盘提交放在一起,避免部分页面只写不提交。

版本迁移只执行一次

字段改名、默认值调整、旧值清理都应该被 schemaVersion 管住。迁移完成后再写入新版本号。

private async migrateIfNeeded(): Promise<void> {
  const pref = this.ensure();
  const version = await pref.get(SettingsKeys.SCHEMA_VERSION, 1) as number;
  if (version < 2) {
    const oldCity = await pref.get('lastCity', '');
    if (oldCity) {
      await pref.put(SettingsKeys.LAST_ROUTE_CITY, oldCity);
      await pref.delete('lastCity');
    }
    await pref.put(SettingsKeys.SCHEMA_VERSION, 2);
    await pref.flush();
  }
}

迁移函数只关注存储结构变化。它先迁移数据,再更新版本号,避免迁移中断后误认为完成。

观察者只刷新必要页面状态

配置变化监听适合刷新设置预览,不适合承担业务流程控制。监听到 key 后再做最小刷新。

startObserve(onChanged: (key: string) => void): void {
  this.ensure().on('change', onChanged);
}

stopObserve(onChanged: (key: string) => void): void {
  this.ensure().off('change', onChanged);
}

观察者生命周期由页面或状态中心管理。注册和反注册成对出现,避免页面销毁后仍然刷新。

删除配置前先确认引用方

Preferences 的字段删除看似简单,但老版本页面、卡片或后台任务仍可能读取。删除前先保留一版兼容读取。

项目 内容
立即删除 只适合未发布字段或确定无读取方字段。
兼容读取 适合已发布字段改名,先读新键再读旧键。
迁移删除 适合升级迁移成功后清理旧字段。

配置验证流程:重启、升级、并发读写都要走一遍

Preferences 的验证不要只看设置页是否显示正确。建议先安装旧版本写入 lastCity 和旧 schemaVersion,再升级到新版本,确认 LAST_ROUTE_CITY 被写入、lastCity 被删除、schemaVersion 变为 2。然后关闭应用进程重新进入,确认地图图层和自动同步开关仍然保持用户选择。最后在设置页反复进入退出,观察 change 监听是否只触发一次,避免生命周期泄漏。

async function verifySettings(store: SettingsStore): Promise<void> {
  const layer = await store.getMapLayer();
  const autoSync = await store.isAutoSyncEnabled();
  console.info(`[SettingsVerify] layer=${layer} autoSync=${autoSync}`);
}

这段验证代码只读业务方法,不直接读底层 Preferences。这样可以证明仓储层提供的默认值、迁移结果和类型转换都能被页面安全使用。

HarmonyOS Preferences 配置治理排查表

现象 优先查看 处理方式
设置重启后丢失 是否调用 flush 显式保存场景写完立即 flush。
升级后旧字段无效 schemaVersion 是否迁移 按版本补迁移并保留兼容读取。
页面反复刷新 change 监听是否未 off 生命周期结束时反注册。
类型判断到处都是 读取入口是否返回原始 ValueType 仓储层转换成业务类型。

HarmonyOS Preferences 配置治理验收清单

上线或交付前建议逐项确认,尤其是生命周期、异常分支和数据一致性。

  • 键名全部集中在一个契约文件。
  • 读取方法都有默认值和类型收口。
  • 迁移函数可重复执行且不会破坏新数据。
  • 写入后有明确 flush 策略。
  • 监听器注册和反注册成对出现。

小结

Preferences 适合轻量配置,但轻量不等于随意。把键名、默认值、迁移、提交和监听边界写清楚,配置数据才不会在版本升级后变成隐性故障源。

参考资料

以下资料用于核对 API 名称和能力边界,落地时请结合项目目标 API 版本复核。

  • HarmonyOS SDK 23 本地 API 声明:@ohos.data.preferences.d.ts
Logo

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

更多推荐