HarmonyOS Preferences 配置治理:键名设计、版本迁移与提交边界
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
更多推荐




所有评论(0)