数据持久化(1):Preferences首选项存储轻量级数据(13)
前言
在鸿蒙(HarmonyOS)应用开发中,数据持久化是保障用户体验的核心环节。当用户设置了深色主题、记住了登录状态或完成了首次引导后,即使应用关闭甚至设备重启,这些状态也不应丢失。Preferences(用户首选项) 正是为此类轻量级数据设计的官方存储方案。它类似于 Android 的 SharedPreferences 或 iOS 的 UserDefaults,专为保存用户的个性化设置等小规模数据而设计。
一、 核心概念与运作机制
Preferences 本质上是一个内存优先 + 异步持久化 + 线程安全的 Key-Value 键值对存储系统。
- 支持类型:Key 必须为字符串;Value 支持
number、string、boolean以及这三种类型的数组。 - 运作机制:所有的读写操作(
get/put)首先直接命中内存中的哈希表,速度极快(微秒级)。当需要落盘时,通过调用flush()接口将数据异步写入到应用沙箱内的文件中。
二、 基础使用实战
从 API Version 18 开始,推荐使用 @kit.ArkData 进行导入。以下展示一个完整的增删改查流程:
import { preferences } from '@kit.ArkData';
import { promptAction, getContext } from '@kit.ArkUI';
@Entry
@Component
struct PreferencesDemo {
// 声明 Preferences 实例
store: preferences.Preferences | null = null;
// 页面即将显示时初始化仓库
aboutToAppear(): void {
this.store = preferences.getPreferencesSync(getContext(this), {
name: 'user-settings' // 仓库名称,唯一标识
});
}
build() {
Column({ space: 15 }) {
Button('保存主题设置')
.onClick(() => {
if (!this.store) return;
// 1. 写入数据到内存
this.store.putSync('theme', 'dark');
this.store.putSync('fontSize', 16);
// 2. 【关键】手动触发持久化到磁盘
this.store.flush();
promptAction.showToast({ message: '保存成功' });
});
Button('读取主题设置')
.onClick(() => {
if (!this.store) return;
// 3. 读取数据(需提供默认值)
const theme = this.store.getSync('theme', 'light');
promptAction.showToast({ message: `当前主题为: ${theme}` });
});
Button('清除特定配置')
.onClick(() => {
if (!this.store) return;
// 4. 删除指定键值对并持久化
this.store.deleteSync('fontSize');
this.store.flush();
});
}
.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
三、 进阶封装:打造全局同步工具类
在实际工程中,为了避免在每个页面重复编写 try-catch 和获取实例的逻辑,建议封装一个基于同步接口的静态工具类:
import { preferences } from '@kit.ArkData';
export class PrefUtil {
private static store: preferences.Preferences | null = null;
// 初始化(建议在 EntryAbility 的 onCreate 中调用)
static init(context: Context) {
if (!this.store) {
this.store = preferences.getPreferencesSync(context, { name: 'appConfig' });
}
}
// 同步保存
static save(key: string, value: preferences.ValueType) {
this.store?.putSync(key, value);
this.store?.flushSync(); // 立即同步落盘
}
// 同步读取
static load<T extends preferences.ValueType>(key: string, defaultValue: T): T {
return this.store?.getSync(key, defaultValue) as T;
}
}
四、 UI 状态联动:结合 @StorageLink
在实际开发中,Preferences 往往需要直接驱动 UI 的更新(例如切换夜间模式)。由于 getSync 是一次性读取,无法自动刷新界面,因此官方推荐将 Preferences 与全局状态容器 AppStorage 结合使用。
// 1. 在 EntryAbility 或初始化阶段,将配置同步到 AppStorage
let store = preferences.getPreferencesSync(context, { name: 'appConfig' });
let isDarkMode = store.getSync('isDarkMode', false);
AppStorage.setOrCreate('isDarkMode', isDarkMode);
// 2. 在页面组件中使用 @StorageLink 实现双向绑定
@Entry
@Component
struct SettingsPage {
// 建立双向绑定:UI 修改会自动触发 AppStorage 和底层存储更新
@StorageLink('isDarkMode') darkMode: boolean = false;
build() {
Row() {
Text('深色模式')
Toggle({ type: ToggleType.Switch, isOn: this.darkMode })
.onChange((isOn: boolean) => {
this.darkMode = isOn;
// 写入本地持久化
let store = preferences.getPreferencesSync(getContext(this), { name: 'appConfig' });
store.putSync('isDarkMode', isOn);
store.flush();
})
}
}
}
五、 数据变更监听:on('change')
当某个配置项被修改时,如果需要在不重启应用的情况下让其他组件做出响应,可以使用 on('change') 订阅数据变化事件。
aboutToAppear(): void {
const store = preferences.getPreferencesSync(getContext(this), { name: 'appConfig' });
// 注册监听器:仅当指定的 key 发生变化时触发
store.on('change', 'fontSize', (key: string, value: preferences.ValueType) => {
console.info(`监听到 ${key} 发生变化,新值为: ${value}`);
// 在这里执行 UI 刷新或重新计算布局等逻辑
});
}
aboutToDisappear(): void {
const store = preferences.getPreferencesSync(getContext(this), { name: 'appConfig' });
// 【关键】页面销毁时务必取消监听,防止内存泄漏
store.off('change');
}
六、 跨模块数据共享:跨 HAR/HSP 访问
在复杂的鸿蒙工程中,通常会有多个业务模块(如 entry 模块和 feature_user 模块)。如果需要跨模块共享首选项,需借助宿主模块的 Context。
import { common } from '@kit.AbilityKit';
// 在 feature_user 模块中读取 entry 模块的配置
let context = getContext(this) as common.UIAbilityContext;
// 注意:这里使用的是当前上下文的文件路径
let store = preferences.getPreferencesSync(context, { name: 'global_config' });
七、 ⚠️ 约束限制与避坑指南
在使用 Preferences 时,务必注意以下硬性限制,否则可能导致文件损坏或严重的性能问题:
- 容量限制:它是轻量级存储,强烈建议单个文件的数据量不超过 50MB(部分场景建议不超过 1万条数据)。若在主线程加载过大的 XML 文件,会导致严重的卡顿甚至 AppFreeze。
- 并发安全:默认的 XML 存储模式不支持多进程并发读写,强行使用会有文件损坏风险。如果是多进程场景,请使用 GSKV 存储模式(API 18+),该模式以二进制存储并支持并发实时落盘。
- 数据安全:Preferences 不支持底层加密。如果需要存储密码等敏感信息,请开发者自行加密后,再以
Uint8Array形式存入。 - 生命周期:首选项文件保存在应用私有沙箱内,应用被卸载时数据会被彻底删除,因此绝不能将其作为关键数据的云端备份手段。
💡 架构选型决策树
虽然 Preferences 极其好用,但它有严格的边界。请遵循以下决策树进行选型:
- 选 Preferences:用户设置、Token 缓存、引导页标记、简单的草稿箱(< 50MB)。
- 选 RDB(关系型数据库):联系人列表、聊天记录、商品库(结构化强、数据量大、需要复杂 SQL 查询)。
- 选 KV-Store(分布式键值对):需要多设备无缝流转、跨端实时同步的数据。
更多推荐

所有评论(0)