HarmonyOS ArkTS 实战:掌握 Preferences 用户首选项(轻量级键值存储)
(用户首选项)是鸿蒙 ArkTS 提供的Key-Value 键值型数据处理能力数据以键值对形式存储,键(Key)为字符串类型,值(Value)支持数字、字符串、布尔型及这 3 种类型的数组;数据持久化存储在应用私有目录,无需手动管理文件路径,系统自动维护;操作 API 简洁(同步 / 异步),开发成本低,读写性能优于关系型数据库。适用场景:仅用于存储轻量级、简单结构的数据(配置、状态标记等),避免
在 HarmonyOS 应用开发中,轻量级数据持久化是高频需求 —— 比如存储用户登录状态、应用启动配置、界面主题偏好、简单的用户设置等。鸿蒙官方提供的Preferences(用户首选项)正是为这类场景设计的键值型存储方案,无需复杂的数据库配置,支持快速的增删改查,是轻量级数据持久化的首选。本文将从核心概念、使用限制、实战代码到避坑指南,全面讲解Preferences的使用方法。
一、Preferences 核心概念与适用场景
1. 什么是 Preferences?
Preferences(用户首选项)是鸿蒙 ArkTS 提供的Key-Value 键值型数据处理能力,专为应用轻量级数据持久化设计:
- 数据以键值对形式存储,键(Key)为字符串类型,值(Value)支持数字、字符串、布尔型及这 3 种类型的数组;
- 数据持久化存储在应用私有目录,无需手动管理文件路径,系统自动维护;
- 操作 API 简洁(同步 / 异步),开发成本低,读写性能优于关系型数据库。
2. 典型适用场景
- 存储应用基础配置:如启动模式(auto/manual)、是否开启推送、界面亮度值;
- 存储用户简单状态:如登录状态标记、最近浏览的试题 ID、默认字体大小;
- 存储临时轻量数据:如表单填写的临时缓存、弹窗是否已展示的标记。
注意:
Preferences不适合存储大量 / 复杂数据(如完整的试题列表、用户日志),这类场景建议使用 RelationalStore(关系型数据库)或分布式数据库。
二、Preferences 使用限制(必看)
使用Preferences前必须遵守以下限制,否则会导致数据存储失败或应用异常:
| 限制类型 | 具体要求 |
|---|---|
| Key 键限制 | ① 类型为 string,非空;② 长度不超过 1024 个字节(约 1KB) |
| Value 值限制 | ① 支持类型:数字、字符串、布尔型及对应数组;② 字符串类型需用 UTF-8 编码;③ 非空字符串长度不超过 16MB(1610241024 字节) |
| 数据量限制 | 建议存储不超过 1 万条数据,否则会占用大量内存,导致应用卡顿 / 崩溃 |
三、实战:Preferences 完整增删改查(附代码解析)
下面基于你提供的核心代码,实现一个完整的Preferences操作示例,包含 “创建仓库、新增、读取、修改、删除、删库” 全流程。
第一步:前置准备(导入依赖)
首先在页面文件中导入Preferences和弹窗提示相关 API:
typescript
运行
import { preferences } from '@kit.ArkData'; // 核心:用户首选项API
import { promptAction, getContext } from '@kit.ArkUI'; // 弹窗提示+上下文获取
第二步:完整代码实现
typescript
运行
@Entry
@Component
struct Demo05Preferences {
// 声明Preferences实例,初始为null
store: preferences.Preferences | null = null;
// 页面即将显示时初始化Preferences仓库(推荐在aboutToAppear中创建)
aboutToAppear(): void {
// 1. 创建/获取Preferences仓库(同步方式)
// 参数1:组件上下文;参数2:配置项(name为仓库名称,唯一标识)
this.store = preferences.getPreferencesSync(getContext(this), {
name: 'test-store' // 仓库名称,自定义(建议语义化命名)
});
}
build() {
Column({ space: 10 }) {
Text('Preferences 首选项操作演示')
.fontSize(20)
.fontWeight(600);
// 按钮1:新增数据(Key: myName, Value: 张飞)
Button('增加')
.onClick(() => {
// 判空:避免store未初始化导致报错
if (!this.store) return;
// 2. 新增/覆盖数据(同步方式)
this.store.putSync('myName', '张飞');
// 3. 刷盘:将内存数据持久化到本地(关键!)
this.store.flush();
promptAction.showToast({ message: '新增成功' });
});
// 按钮2:读取数据
Button('读取')
.onClick(() => {
if (!this.store) return;
// 4. 读取数据(同步方式)
// 参数1:要读取的Key;参数2:默认值(Key不存在时返回)
const value = this.store.getSync('myName', '');
// 打印+弹窗展示结果
console.log('读取到的值:', value?.toString());
promptAction.showToast({ message: `读取结果:${value || '无数据'}` });
});
// 按钮3:修改数据(覆盖已有Key的值)
Button('修改')
.onClick(() => {
if (!this.store) return;
// 5. 修改数据(putSync会覆盖已有Key的值)
this.store.putSync('myName', '貂蝉');
this.store.flush(); // 必须刷盘才能持久化
promptAction.showToast({ message: '修改成功' });
});
// 按钮4:删除指定Key的数据
Button('删除')
.onClick(() => {
if (!this.store) return;
// 6. 删除指定Key
this.store.deleteSync('myName');
this.store.flush(); // 刷盘确认删除
promptAction.showToast({ message: '删除成功' });
});
// 按钮5:删除整个Preferences仓库
Button('删库')
.backgroundColor('#ff4444')
.fontColor('#ffffff')
.onClick(() => {
try {
// 7. 删除整个仓库(谨慎使用!)
preferences.deletePreferences(getContext(this), {
name: 'test-store'
});
this.store = null; // 清空实例,避免后续操作报错
promptAction.showToast({ message: '仓库删除成功' });
} catch (e) {
console.error('删库失败:', e);
promptAction.showToast({ message: '删库失败' });
}
});
}
.padding({ top: 40 })
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center);
}
}
核心代码解析
1. 仓库初始化(创建 / 获取)
typescript
运行
this.store = preferences.getPreferencesSync(getContext(this), { name: 'test-store' });
getPreferencesSync:同步获取 Preferences 实例,若指定名称的仓库不存在则自动创建;getContext(this):传递当前组件的上下文,是操作 Preferences 的必要参数(不能传字符串 'this',这是常见错误);- 仓库名称(name):唯一标识一个 Preferences 仓库,建议按业务模块命名(如 'user_setting'、'app_config')。
2. 新增 / 修改数据
typescript
运行
this.store.putSync('myName', '张飞');
this.store.flush();
putSync(key, value):新增或修改数据(Key 存在则覆盖,不存在则新增);flush():核心!putSync仅将数据写入内存,需调用flush()才能将内存数据持久化到本地文件,否则应用重启后数据丢失。
3. 读取数据
typescript
运行
const value = this.store.getSync('myName', '');
getSync(key, defaultValue):读取指定 Key 的值,第二个参数为默认值(Key 不存在 / 读取失败时返回);- 返回值类型与存储的 Value 类型一致,建议用
toString()统一处理(避免类型异常)。
4. 删除指定 Key
typescript
运行
this.store.deleteSync('myName');
this.store.flush();
deleteSync(key):删除指定 Key 的键值对,同样需要flush()刷盘确认。
5. 删除整个仓库
typescript
运行
preferences.deletePreferences(getContext(this), { name: 'test-store' });
deletePreferences:删除整个 Preferences 仓库(所有键值对都会被删除),需谨慎使用;- 删库后建议将
store实例置为null,避免后续操作已删除的仓库导致报错。
四、关键避坑指南
1. 忘记调用 flush (),数据丢失
这是最常见的错误!putSync/deleteSync仅修改内存数据,必须调用 flush () 才能持久化。若未调用,应用重启后数据会恢复到上次 flush 的状态。
2. 上下文传递错误
错误写法:
typescript
运行
preferences.deletePreferences(getContext('this'), { name: 'test-store' });
正确写法:
typescript
运行
preferences.deletePreferences(getContext(this), { name: 'test-store' });
getContext的参数是组件实例this,而非字符串 'this',否则会导致上下文无效,操作失败。
3. Key/Value 超出长度限制
- Key 长度超过 1024 字节:会直接抛出异常,建议 Key 简洁(如 'use_push' 而非 'user_setting_notification_push_status');
- 字符串 Value 超过 16MB:会导致存储失败,这类大文本建议用文件存储(fileIo)。
4. 同步 API 阻塞主线程
示例中使用的getPreferencesSync/putSync等是同步 API,若操作大量数据(虽不建议),会阻塞 UI 主线程,导致页面卡顿。推荐使用异步 API:
typescript
运行
// 异步创建仓库示例
async initStore() {
try {
this.store = await preferences.getPreferences(getContext(this), { name: 'test-store' });
} catch (e) {
console.error('初始化仓库失败:', e);
}
}
// 异步新增数据示例
async addData() {
if (!this.store) return;
await this.store.put('myName', '赵云');
await this.store.flush();
}
5. 数据量过大导致内存溢出
若存储超过 1 万条数据,会显著增加应用内存占用,建议:
- 高频更新的大量数据改用数据库;
- 定期清理无用数据(如过期的缓存 Key)。
五、扩展优化建议
1. 封装工具类(复用 Preferences 操作)
将 Preferences 的增删改查封装为工具类,避免重复代码:
typescript
运行
// utils/PreferencesUtil.ets
import { preferences } from '@kit.ArkData';
import { getContext } from '@kit.ArkUI';
export class PreferencesUtil {
private static store: preferences.Preferences | null = null;
// 初始化仓库
public static async init(storeName: string = 'default-store') {
if (!this.store) {
this.store = await preferences.getPreferences(getContext(globalThis), { name: storeName });
}
return this.store;
}
// 存储数据
public static async set(key: string, value: any) {
if (!this.store) await this.init();
await this.store?.put(key, value);
await this.store?.flush();
}
// 读取数据
public static async get(key: string, defaultValue: any = '') {
if (!this.store) await this.init();
return this.store?.get(key, defaultValue) || defaultValue;
}
// 删除数据
public static async remove(key: string) {
if (!this.store) await this.init();
await this.store?.delete(key);
await this.store?.flush();
}
}
2. 添加错误处理
所有 Preferences 操作建议包裹try/catch,避免异常导致应用崩溃:
typescript
运行
Button('增加')
.onClick(async () => {
try {
if (!this.store) return;
await this.store.put('myName', '张飞');
await this.store.flush();
promptAction.showToast({ message: '新增成功' });
} catch (e) {
console.error('新增失败:', e);
promptAction.showToast({ message: '新增失败,请重试' });
}
});
3. 支持数组类型存储
Preferences 支持数组类型(数字 / 字符串 / 布尔数组),示例:
typescript
运行
// 存储字符串数组
this.store.putSync('favorite_questions', ['1001', '1002', '1003']);
this.store.flush();
// 读取数组
const favorite = this.store.getSync('favorite_questions', []);
console.log('收藏的试题ID:', favorite);
六、总结
Preferences是鸿蒙应用轻量级键值存储的最佳选择,核心要点可总结为:
- 适用场景:仅用于存储轻量级、简单结构的数据(配置、状态标记等),避免存储大量 / 复杂数据;
- 核心操作:增删改查后必须调用
flush(),否则数据仅存于内存,重启后丢失; - 避坑重点:正确传递上下文、遵守 Key/Value 长度限制、优先使用异步 API 避免阻塞主线程;
- 最佳实践:封装工具类复用代码,添加错误处理,定期清理无用数据。
掌握Preferences的使用,能高效解决鸿蒙应用中轻量级数据持久化的需求,相比数据库更简洁、更高效,是 ArkTS 开发必备的基础技能之一。
更多推荐


所有评论(0)