摘要Preferences 是 OpenHarmony 轻量键值持久化存储组件用于保存小型配置数据应用重启、设备关机后数据不会丢失常与 AppStorage 全局内存状态搭配使用实现「内存实时读写 磁盘永久保存」双缓存架构适配登录缓存、主题偏好、设置开关、搜索历史、用户基础配置等轻量数据场景。API Version23 重构 Preferences 文件读写、多实例锁、异步回调、类型序列化逻辑修复低版本存储写入丢失、并发读写错乱、布尔 / 数字读取默认值异常、多页面同时操作文件冲突等兼容缺陷。低版本工程升级至 API23 后普遍出现保存的数据重启应用消失、并发读写覆盖数据、读取数字返回 0、布尔值读取恒为 false、存储文件损坏等故障。本文基于 DevEco Studio 适配 OpenHarmony API23 及以上版本讲解 Preferences 同步 / 异步读写、多类型存取、封装全局存储工具类、与 AppStorage 联动持久化、分页搜索历史存储输出并发读写锁、存储性能优化、异常容错规范汇总版本升级兼容故障解决方案为鸿蒙轻量本地持久化开发提供标准化实操模板。关键词OpenHarmonyArkUIAPI Version23Preferences本地持久化键值存储持久化全局配置AppStorage 联动轻量缓存一、引言1.1 Preferences 开发背景AppStorage 仅存在应用内存进程杀死数据全部销毁无法实现永久配置保存数据库适合海量复杂数据存储小型开关、用户名、主题标识会产生性能冗余。Preferences 作为系统原生轻量持久化方案以 XML 文件形式持久化至应用沙盒目录仅支持基础键值类型读写速度快、API 简洁是应用配置类数据首选存储方案。OpenHarmony API Version23 针对 Preferences 底层文件 IO 引擎做全面升级核心变更点新增文件读写互斥锁同一存储文件多页面并发读写不再互相覆盖统一基础类型序列化规则string/number/boolean 读取不会出现默认值错乱优化异步 getPreferences 加载逻辑修复低版本文件加载延迟导致读取空值规范 flush 持久化强制落盘机制区分内存缓存与磁盘持久化增加文件损坏自动兜底默认值逻辑避免应用闪退限制超大字符串、数组直接存入 Preferences给出性能告警。大量 API9~11 旧项目升级后切换深色模式重启失效、登录状态重启丢失、搜索历史保存不全根源是旧版无锁并发写入、未强制 flush 落盘因此掌握 API23 标准 Preferences 封装规范是配置类开发必备技能。1.2 开发环境与测试场景开发工具DevEco Studio 5.0 及以上 适配系统OpenHarmony API Version23、HarmonyOS NEXT 开发语言ArkTS 导入模块ohos.data.preferences 测试场景深色主题持久保存、登录状态本地缓存、用户昵称永久存储、搜索历史数组持久化、AppStorage 全局配置落地磁盘、多页面并发读写配置文件二、API23 Preferences 核心 API 与版本变更说明2.1 核心对象获取方式API23 标准异步写法etsimport preferences from ohos.data.preferences // 获取Preferences实例fileName为沙盒内存储文件名 async function getPrefInstance() { let dataPreferences await preferences.getPreferences(getContext(this), app_config) return dataPreferences }2.2 数据写入与落盘putSync (key, value)同步写入内存缓存put (key, value)异步写入内存缓存flush ()强制将内存缓存数据写入磁盘文件API23 必须调用否则进程销毁丢失2.3 数据读取 APIgetSyncT(key, defaultValue) 同步读取getT(key, defaultValue) 异步读取无数据返回默认值。 支持类型string、number、boolean、Arraystring2.4 删除与清空deleteSync (key) 删除单条键clearSync () 清空全部存储hasSync (key) 判断键是否存在。2.5 API23 废弃与强制约束废弃无 flush 直接退出进程写法不执行 flush 会丢失本次写入禁止多实例同时操作同一个 fileName 文件必须全局单例管理废弃复杂对象直接存储对象需 JSON 序列化字符串后存取单条字符串存储长度上限 8000 字符超长数据拆分或改用数据库同步 API 禁止在主线程循环大量调用易造成页面卡顿。三、API23 标准基础示例代码3.1 基础布尔值持久化深色模式开关etsimport preferences from ohos.data.preferences // 保存深色模式开关 async function saveDarkMode(isDark: boolean) { let pref await preferences.getPreferences(getContext(), app_config) pref.putSync(dark_mode, isDark) await pref.flush() // API23必须强制落盘 } // 读取深色模式无数据默认false async function getDarkMode(): Promiseboolean { let pref await preferences.getPreferences(getContext(), app_config) let val pref.getSync(dark_mode, false) return val }3.2 字符串持久化登录用户名etsasync function saveUserName(name: string) { let pref await preferences.getPreferences(getContext(), app_config) pref.putSync(user_name, name) await pref.flush() } async function getUserName(): Promisestring { let pref await preferences.getPreferences(getContext(), app_config) return pref.getSync(user_name, 游客) }3.3 数组存储搜索历史JSON 序列化etsasync function saveSearchHistory(list: string[]) { let pref await preferences.getPreferences(getContext(), app_config) let jsonStr JSON.stringify(list) pref.putSync(search_history, jsonStr) await pref.flush() } async function getSearchHistory(): Promisestring[] { let pref await preferences.getPreferences(getContext(), app_config) let jsonStr pref.getSync(search_history, []) return JSON.parse(jsonStr) }四、四大业务完整实战案例全兼容 API234.1 实战一全局 Preferences 工具类单例封装项目通用新建 utils/preference_utils.ets全局统一存取避免多实例冲突etsimport preferences from ohos.data.preferences import common from ohos.app.ability.common class PreferenceUtil { private static instance: PreferenceUtil private pref: preferences.Preferences | null null private readonly FILE_NAME app_global_config static getInstance(): PreferenceUtil { if (!PreferenceUtil.instance) { PreferenceUtil.instance new PreferenceUtil() } return PreferenceUtil.instance } // 初始化存储实例页面启动调用一次 async init(context: common.UIAbilityContext) { this.pref await preferences.getPreferences(context, this.FILE_NAME) } // 保存布尔值 async putBool(key: string, value: boolean) { if (!this.pref) return this.pref.putSync(key, value) await this.pref.flush() } async getBool(key: string, def: boolean false): Promiseboolean { if (!this.pref) return def return this.pref.getSync(key, def) } // 保存字符串 async putString(key: string, value: string) { if (!this.pref) return this.pref.putSync(key, value) await this.pref.flush() } async getString(key: string, def: string ): Promisestring { if (!this.pref) return def return this.pref.getSync(key, def) } // 保存数字 async putNumber(key: string, value: number) { if (!this.pref) return this.pref.putSync(key, value) await this.pref.flush() } async getNumber(key: string, def: number 0): Promisenumber { if (!this.pref) return def return this.pref.getSync(key, def) } // 数组序列化存储 async putArrayT(key: string, arr: T[]) { if (!this.pref) return let str JSON.stringify(arr) this.pref.putSync(key, str) await this.pref.flush() } async getArrayT(key: string): PromiseT[] { if (!this.pref) return [] let str this.pref.getSync(key, []) return JSON.parse(str) } // 删除单条key async deleteKey(key: string) { if (!this.pref) return this.pref.deleteSync(key) await this.pref.flush() } // 清空全部存储 async clearAll() { if (!this.pref) return this.pref.clearSync() await this.pref.flush() } } export default PreferenceUtil.getInstance()4.2 实战二Preferences AppStorage 联动持久化主题实现页面修改开关同步 AppStorage 内存同时写入 Preferences 磁盘应用重启自动读取 Preferences 回填全局状态etsimport prefUtil from ../utils/preference_utils Entry Component struct ThemePage { StorageLink(darkMode) darkSwitch: boolean false async aboutToAppear() { // 页面加载从本地持久化读取初始化全局状态 await prefUtil.init(getContext(this)) let localDark await prefUtil.getBool(dark_mode) AppStorage.Set(darkMode, localDark) this.darkSwitch localDark } // 切换开关同步内存与本地存储 async changeTheme(val: boolean) { this.darkSwitch val AppStorage.Set(darkMode, val) await prefUtil.putBool(dark_mode, val) } build() { Column({ space: 25 }) { Text(持久化深色主题设置) .fontSize(22) .fontWeight(FontWeight.Bold) Row() { Text(夜间模式).layoutWeight(1).fontSize(17) Toggle({ isOn: this.darkSwitch }) .onChange(async v await this.changeTheme(v)) } .width(100%) .height(56) .padding(15) .backgroundColor(Color.White) .borderRadius(10) Text(关闭应用重新打开配置不会丢失) .fontSize(14) .fontColor(#999) } .width(100%) .height(100%) .padding(20) .backgroundColor(this.darkSwitch ? #1A1A1A : #F5F5F5) } }4.3 实战三登录信息本地持久缓存重启免登etsimport prefUtil from ../utils/preference_utils import router from ohos.router Entry Component struct LoginPage { State account: string State pwd: string async aboutToAppear() { await prefUtil.init(getContext(this)) // 读取上次登录账号回填输入框 let saveAccount await prefUtil.getString(login_account) this.account saveAccount } async handleLogin() { if (this.account.length 1) { promptAction.showToast({ message: 账号不能为空 }) return } // 登录成功存入本地持久化与全局AppStorage await prefUtil.putString(login_account, this.account) await prefUtil.putBool(is_login, true) AppStorage.Set(isLogin, true) AppStorage.Set(userName, this.account) router.replaceUrl({ url: pages/mine/mine }) } build() { Column({ space: 22 }) { Text(账号登录持久化缓存) .fontSize(24) .fontWeight(FontWeight.Bold) TextInput({ text: this.account, placeholder: 输入账号 }) .width(100%) .height(48) .onChange(v this.account v) TextInput({ text: this.pwd, placeholder: 输入密码 }) .type(InputType.Password) .width(100%) .height(48) Button(登录并保存账号) .width(100%) .height(48) .backgroundColor(#007DFF) .onClick(async () await this.handleLogin()) } .width(100%) .height(100%) .padding(25) .justifyContent(FlexAlign.Center) } }4.4 实战四搜索历史数组持久存取etsimport prefUtil from ../utils/preference_utils Entry Component struct SearchPage { State keyword: string State historyList: string[] [] async aboutToAppear() { await prefUtil.init(getContext(this)) // 读取本地历史记录 this.historyList await prefUtil.getArraystring(search_history) } // 新增搜索词并持久保存 async addHistory() { if (!this.keyword) return // 去重 let idx this.historyList.indexOf(this.keyword) if (idx -1) this.historyList.splice(idx, 1) this.historyList.unshift(this.keyword) // 限制最多8条历史 if (this.historyList.length 8) this.historyList.pop() // 存入本地持久化 await prefUtil.putArray(search_history, this.historyList) this.keyword } build() { Column({ space: 18 }) { Row({ space: 10 }) { TextInput({ text: this.keyword, placeholder: 输入搜索内容 }) .layoutWeight(1) .height(44) Button(搜索) .height(44) .onClick(async () await this.addHistory()) } Text(搜索历史).fontSize(18).fontWeight(FontWeight.Medium) List({ space: 8 }) { ForEach(this.historyList, (item: string) { ListItem() { Text(item).width(100%).padding(12).backgroundColor(Color.White).borderRadius(8) } }) } .layoutWeight(1) } .width(100%) .height(100%) .padding(15) } }五、API23 持久化存储适配与性能优化规范5.1 多页面并发读写规范全局使用单例工具类管理 Preferences 实例禁止每个页面新建实例每次 put 操作后必须执行 await flush () 强制落盘API23 无自动持久化短时间连续多次写入增加防抖避免高频 flush 重复 IO 操作启动页统一初始化 pref 实例子页面直接调用工具类无需重复 init。5.2 数据存储分层规范临时页面变量State页面销毁丢失全局内存共享配置AppStorage进程杀死丢失永久保存配置Preferences双缓存架构AppStoragePreferences海量结构化数据、图片二进制使用 RDB 关系型数据库不使用 Preferences。5.3 性能优化准则不存储超长文本、大型 JSON 对象拆分精简字段主线程避免循环同步 get/put 大量数据改用异步 API退出登录、重置功能调用 clearAll 清空冗余配置减少文件体积数组统一 JSON 序列化存储API23 不支持直接传入数组参数。六、API23 升级高频兼容问题与解决方案问题 1重启应用后保存的配置全部消失 解决每次写入后必须执行await pref.flush()强制写入磁盘旧版本隐性落盘逻辑在 API23 已移除。问题 2多页面同时读写同一配置数据互相覆盖错乱 解决全局单例工具类统一管控实例利用 API23 内置文件互斥锁禁止多实例操作同一文件。问题 3读取布尔值恒为 false、数字恒为 0 解决读取时传入正确默认值旧项目升级统一替换同步 getSync异步 get 需 await 接收返回。问题 4数组存入后读取解析报错 解决复杂数组 / 对象必须 JSON.stringify 序列化字符串存储读取后 JSON.parse 还原。问题 5页面频繁切换存储读写页面滑动卡顿 解决增加防抖延迟合并短时间多次写入操作减少 flush 磁盘 IO 次数。问题 6升级后旧存储文件读取失败、返回默认值 解决初始化时增加异常捕获文件损坏自动使用默认值覆盖重建配置文件。七、总结Preferences 是 OpenHarmony 轻量本地持久化标准组件API Version23 重构文件 IO 并发锁、数据序列化、强制落盘机制解决旧版数据丢失、并发错乱核心缺陷。项目标准架构为「Preferences 磁盘持久化 AppStorage 全局内存缓存」启动时从本地读取回填全局状态修改时同步更新内存与磁盘兼顾实时响应与永久保存。