OpenHarmony Preferences 本地持久化存储实战详解
在 OpenHarmony 应用开发中,Preferences 偏好存储常用于保存轻量键值对数据:用户配置、登录状态、开关设置、缓存标识等,数据持久保存在本地,应用重启、设备关机后数据不丢失。相较于数据库,Preferences 使用简单、专注字符串 / 数字 / 布尔等基础类型,是项目高频本地存储方案。本篇完整讲解 API 用法、存取、删除、同步 / 异步操作,搭配落地代码。
·
一、前言
在 OpenHarmony 应用开发中,Preferences 偏好存储常用于保存轻量键值对数据:用户配置、登录状态、开关设置、缓存标识等,数据持久保存在本地,应用重启、设备关机后数据不丢失。相较于数据库,Preferences 使用简单、专注字符串 / 数字 / 布尔等基础类型,是项目高频本地存储方案。本篇完整讲解 API 用法、存取、删除、同步 / 异步操作,搭配落地代码。
依赖模块:
@ohos.data.preferences
二、核心基础概念
- Preferences 实例:以文件名区分数据库,一个文件对应一套独立键值数据;
- 存储数据类型:支持
string、number、boolean、Array<string>四种; - 数据落盘:写入数据后必须调用
flush()才会持久化写入磁盘,否则只在内存。
三、前置导入
ets
import preferences from '@ohos.data.preferences'
import common from '@ohos.app.ability.common'
获取上下文 Context(Ability 上下文,存储必备参数)。
四、基础 CRUD 案例
4.1 封装获取 Preferences 工具对象
ets
// 获取偏好存储实例
async function getPrefer(context: common.UIAbilityContext, fileName: string) {
let prefer = await preferences.getPreferences(context, fileName)
return prefer
}
4.2 写入 & 保存数据
ets
@Entry
@Component
struct PreWriteDemo {
// 上下文
context = getContext(this) as common.UIAbilityContext
async saveData() {
// 打开userinfo.xml存储文件
let prefer = await getPrefer(this.context, "userinfo")
// 存入多组键值
prefer.putSync("username", "Harmony开发者")
prefer.putSync("age", 22)
prefer.putSync("isLogin", true)
prefer.putSync("hobby", ["编程", "嵌入式", "鸿蒙开发"])
// 关键:持久化落地磁盘
await prefer.flush()
console.info("数据保存成功")
}
build() {
Column() {
Button("保存用户信息")
.width(200)
.onClick(() => this.saveData())
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
4.3 读取本地存储数据
ets
@Entry
@Component
struct PreReadDemo {
@State name: string = ""
@State age: number = 0
@State loginStat: boolean = false
context = getContext(this) as common.UIAbilityContext
async readData() {
let prefer = await getPrefer(this.context, "userinfo")
// 参数:键名、默认值(无数据时返回默认)
this.name = prefer.getSync("username", "未知用户")
this.age = prefer.getSync("age", 0)
this.loginStat = prefer.getSync("isLogin", false)
}
build() {
Column({ space: 15 }) {
Button("读取存储数据").onClick(() => this.readData())
Text(`用户名:${this.name}`).fontSize(18)
Text(`年龄:${this.age}`).fontSize(18)
Text(`登录状态:${this.loginStat ? "已登录" : "未登录"}`).fontSize(18)
}
.padding(30)
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
4.4 删除指定键、清空全部数据
ets
@Entry
@Component
struct PreDelDemo {
context = getContext(this) as common.UIAbilityContext
// 删除单个key
async delKey() {
let prefer = await getPrefer(this.context, "userinfo")
prefer.deleteSync("age")
await prefer.flush()
console.info("age字段删除完成")
}
// 清空当前文件所有数据
async clearAll() {
let prefer = await getPrefer(this.context, "userinfo")
prefer.clearSync()
await prefer.flush()
console.info("全部数据清空")
}
build() {
Column({ space:20 }) {
Button("删除age字段").onClick(()=>this.delKey())
Button("清空全部数据").onClick(()=>this.clearAll())
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
五、异步写法(Promise 方式,项目主流)
除了putSync/getSync同步 API,官方推荐异步 API 避免阻塞 UI 线程:
ets
async function asyncOpt(context: common.UIAbilityContext) {
let prefer = await preferences.getPreferences(context, "setting")
// 异步存
await prefer.put("nightMode", true)
// 异步读
let res = await prefer.get("nightMode", false)
console.info("夜间模式:" + res)
await prefer.flush()
}
六、综合实战:应用设置页持久化开关
结合之前 Toggle 开关组件,实现开关状态永久保存,重启 APP 状态不变
ets
import preferences from '@ohos.data.preferences'
import common from '@ohos.app.ability.common'
@Component
struct getPreferTool {
static async getPre(context: common.UIAbilityContext, name: string) {
return await preferences.getPreferences(context, name)
}
}
@Entry
@Component
struct SettingStorePage {
@State nightOpen: boolean = false
@State notifyOpen: boolean = false
context = getContext(this) as common.UIAbilityContext
aboutToAppear() {
// 页面加载读取本地存储
this.loadSetting()
}
// 读取配置
async loadSetting() {
let pre = await getPreferTool.getPre(this.context, "app_setting")
this.nightOpen = await pre.get("nightMode", false)
this.notifyOpen = await pre.get("notify", true)
}
// 保存配置
async saveSetting() {
let pre = await getPreferTool.getPre(this.context, "app_setting")
await pre.put("nightMode", this.nightOpen)
await pre.put("notify", this.notifyOpen)
await pre.flush()
}
build() {
Column({ space: 20 }) {
Text("系统偏好设置").fontSize(22).fontWeight(FontWeight.Bold).margin({bottom:20})
Row() {
Text("夜间模式").fontSize(18).layoutWeight(1)
Toggle({ isOn: this.nightOpen })
.onChange((v: boolean) => {
this.nightOpen = v
this.saveSetting()
})
}
.width("100%")
.padding(15)
.backgroundColor("#fff")
.borderRadius(8)
Row() {
Text("消息推送").fontSize(18).layoutWeight(1)
Toggle({ isOn: this.notifyOpen })
.onChange((v: boolean) => {
this.notifyOpen = v
this.saveSetting()
})
}
.width("100%")
.padding(15)
.backgroundColor("#fff")
.borderRadius(8)
}
.width("100%")
.height("100%")
.padding(20)
.backgroundColor("#f5f5f5")
}
}
效果:修改开关后自动落地本地,关闭应用再次打开,开关状态和上次一致。
七、开发使用规范与注意事项
- 适用场景
- ✅ 小型配置、登录标记、开关状态、用户简单信息
- ❌ 大批量数据、复杂结构化数据(改用关系型数据库 RDB)
- flush () 必写:所有修改操作后必须执行 flush,否则数据仅存在内存,卸载 / 重启丢失;
- 文件名规范:按业务拆分文件,用户数据 user.xml、配置 setting.xml,不要全部塞进同一个文件;
- 默认值:get 时必须设置兜底默认值,防止 key 不存在返回 undefined 导致页面报错。
更多推荐



所有评论(0)