HarmonyOS鸿蒙Next中如何使用Preferences实现轻量级数据存储?
HarmonyOS鸿蒙Next中如何使用Preferences实现轻量级数据存储? 1.如何使用鸿蒙Preferences实现轻量级数据存储? 2. 如何处理复杂对象的序列化?
【背景知识】
[@ohos.data.preferences (用户首选项)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-data-preferences):
用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。
数据存储采用键值对形式,键为字符串类型,值可为数字、字符、布尔类型及其对应的数组。
用户首选项的持久化文件存储在preferencesDir路径下,创建preferences对象前,需要保证preferencesDir路径可读写。持久化文件存储路径中的加密等级会影响文件的可读写状态,路径访问限制详见应用文件目录与应用文件路径。
【参考方案】
- 可参考字体大小调节示例,通过滑动组件Slider与[@ohos.data.preferences](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-data-preferences)实现应用内的字体大小调节,并实现屏蔽系统字体大小设置功能,用户可以按需调整当前阅读内容字体大小。
// 在首选项中设置字体大小
saveChangeFontSize(fontSize: number) {
try {
let fontPreferences: preferences.Preferences = this.getFontPreferences();
fontPreferences.putSync(KEY_APP_FONT_SIZE, fontSize);
fontPreferences.flushSync();
} catch (err) {
// ...
}
}
// 从首选项中读取字体大小
getChangeFontSize(): number {
let defaultFontSize: number = 0;
let fontPreferences: preferences.Preferences = this.getFontPreferences();
let fontSize: number = fontPreferences.getSync(KEY_APP_FONT_SIZE, defaultFontSize) as number;
return fontSize;
}
- 使用Slider组件实现字体大小的滑动选择,每次滑动后调用[@ohos.data.preferences](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-data-preferences)对最新字体大小进行存储。
Slider({
value: this.changeFontSize === CommonConstants.SET_SIZE_HUGE
? CommonConstants.SET_SLIDER_MAX : this.changeFontSize,
min: CommonConstants.SET_SLIDER_MIN, // 滑动最小值
max: CommonConstants.SET_SLIDER_MAX, // 滑动最大值
step: CommonConstants.SET_SLIDER_STEP, // 步长
// 其他设置
})
.onChange((value: number) => {
if (this.changeFontSize === 0) {
this.changeFontSize = PreferencesUtil.getChangeFontSize();
return;
}
this.changeFontSize = value
PreferencesUtil.saveChangeFontSize(this.changeFontSize);
this.changeFontSize = PreferencesUtil.getChangeFontSize()
})
更多关于HarmonyOS鸿蒙Next中如何使用Preferences实现轻量级数据存储?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
实现代码
import { preferences } from '@kit.ArkData';
import { common } from '@kit.AbilityKit';
/**
* 应用设置模型
*/
export interface AppSettings {
theme: string; // 主题模式
themeColorId: string; // 主题色ID
fontSize: string; // 字体大小
viewMode: string; // 视图模式
defaultRecordType: string; // 默认记录类型
customAmounts: number[]; // 自定义快捷金额
customEventTypes: string[]; // 自定义事件类型
reciprocationGrowthRate: number; // 待回礼增长比例
autoBackup: boolean; // 自动备份开关
autoBackupFrequency: string; // 备份频率
maxBackupCount: number; // 最大备份数
lastBackupTime: number; // 最后备份时间
biometricAuth: boolean; // 生物识别认证
notificationEnabled: boolean; // 通知开关
syncEnabled: boolean; // 同步开关
}
/**
* Preferences存储服务
*/
export class PreferencesService {
private static instance: PreferencesService;
private preferencesStore: preferences.Preferences | null = null;
private readonly STORE_NAME = 'app_settings';
private constructor() {}
static getInstance(): PreferencesService {
if (!PreferencesService.instance) {
PreferencesService.instance = new PreferencesService();
}
return PreferencesService.instance;
}
/**
* 初始化Preferences
*/
async init(context: common.UIAbilityContext): Promise<void> {
try {
this.preferencesStore = await preferences.getPreferences(
context,
this.STORE_NAME
);
console.info('Preferences初始化成功');
} catch (err) {
console.error('Preferences初始化失败:', JSON.stringify(err));
throw new Error('Preferences初始化失败');
}
}
/**
* 保存应用设置
*/
async saveSettings(settings: AppSettings): Promise<void> {
try {
if (!this.preferencesStore) {
throw new Error('Preferences未初始化');
}
// 将对象序列化为JSON字符串
const settingsJson = JSON.stringify(settings);
// 保存到Preferences
await this.preferencesStore.put('settings', settingsJson);
// 立即持久化到磁盘
await this.preferencesStore.flush();
console.info('设置保存成功');
} catch (err) {
console.error('保存设置失败:', JSON.stringify(err));
throw new Error('保存设置失败');
}
}
/**
* 加载应用设置
*/
async loadSettings(): Promise<AppSettings> {
try {
if (!this.preferencesStore) {
throw new Error('Preferences未初始化');
}
// 从Preferences读取
const settingsJson = await this.preferencesStore.get('settings', '');
if (!settingsJson) {
// 返回默认设置
return this.getDefaultSettings();
}
// 反序列化JSON
const settings = JSON.parse(settingsJson as string) as AppSettings;
return settings;
} catch (err) {
console.error('加载设置失败:', JSON.stringify(err));
return this.getDefaultSettings();
}
}
/**
* 获取默认设置
*/
private getDefaultSettings(): AppSettings {
return {
theme: 'auto',
themeColorId: 'orange',
fontSize: 'medium',
viewMode: 'list',
defaultRecordType: 'sent',
customAmounts: [100, 200, 500, 600, 1000],
customEventTypes: [],
reciprocationGrowthRate: 1.0,
autoBackup: true,
autoBackupFrequency: 'daily',
maxBackupCount: 7,
lastBackupTime: 0,
biometricAuth: false,
notificationEnabled: true,
syncEnabled: false
};
}
/**
* 更新单个设置项
*/
async updateSetting<K extends keyof AppSettings>(
key: K,
value: AppSettings[K]
): Promise<void> {
try {
const settings = await this.loadSettings();
settings[key] = value;
await this.saveSettings(settings);
} catch (err) {
console.error('更新设置失败:', JSON.stringify(err));
throw new Error('更新设置失败');
}
}
/**
* 获取单个设置项
*/
async getSetting<K extends keyof AppSettings>(
key: K
): Promise<AppSettings[K]> {
const settings = await this.loadSettings();
return settings[key];
}
/**
* 删除所有设置(恢复默认)
*/
async resetSettings(): Promise<void> {
try {
if (!this.preferencesStore) {
throw new Error('Preferences未初始化');
}
await this.preferencesStore.delete('settings');
await this.preferencesStore.flush();
console.info('设置已重置');
} catch (err) {
console.error('重置设置失败:', JSON.stringify(err));
throw new Error('重置设置失败');
}
}
/**
* 保存简单键值对
*/
async put(key: string, value: string | number | boolean): Promise<void> {
try {
if (!this.preferencesStore) {
throw new Error('Preferences未初始化');
}
await this.preferencesStore.put(key, value);
await this.preferencesStore.flush();
} catch (err) {
console.error('保存数据失败:', JSON.stringify(err));
throw new Error('保存数据失败');
}
}
/**
* 获取简单键值对
*/
async get(key: string, defaultValue: string | number | boolean): Promise<string | number | boolean> {
try {
if (!this.preferencesStore) {
throw new Error('Preferences未初始化');
}
return await this.preferencesStore.get(key, defaultValue);
} catch (err) {
console.error('获取数据失败:', JSON.stringify(err));
return defaultValue;
}
}
}
使用示例
// 在EntryAbility中初始化
export default class EntryAbility extends UIAbility {
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
const prefsService = PreferencesService.getInstance();
await prefsService.init(this.context);
// 加载设置
const settings = await prefsService.loadSettings();
console.log('当前主题:', settings.theme);
}
}
// 在设置页面中使用
@Entry
@Component
struct SettingsPage {
@State settings: AppSettings = {} as AppSettings;
private prefsService = PreferencesService.getInstance();
async aboutToAppear() {
this.settings = await this.prefsService.loadSettings();
}
// 切换主题
async onThemeChange(theme: string) {
await this.prefsService.updateSetting('theme', theme);
this.settings.theme = theme;
}
// 更新快捷金额
async onCustomAmountsChange(amounts: number[]) {
await this.prefsService.updateSetting('customAmounts', amounts);
this.settings.customAmounts = amounts;
}
build() {
Column() {
Text(`当前主题: ${this.settings.theme}`)
Text(`快捷金额: ${this.settings.customAmounts.join(', ')}`)
}
}
}
原理解析
1. Preferences初始化
preferences.getPreferences(context, 'app_settings')
- 需要传入UIAbilityContext
- 指定存储名称(文件名)
- 返回Preferences实例
2. 复杂对象序列化
JSON.stringify(settings) // 保存时
JSON.parse(settingsJson) // 读取时
- Preferences只支持基本类型
- 复杂对象需要JSON序列化
- 注意类型转换
3. 立即持久化
await this.preferencesStore.flush();
- put()只是写入内存
- flush()才会持久化到磁盘
- 确保数据不丢失
4. 泛型类型安全
async updateSetting<K extends keyof AppSettings>(
key: K,
value: AppSettings[K]
)
- 使用泛型约束key
- 保证value类型正确
- 编译时类型检查
最佳实践
- 单例模式: 全局只有一个Preferences实例
- 默认值: 读取失败时返回默认设置
- 立即持久化: 重要数据修改后立即flush()
- 异常处理: 所有操作都要try-catch
- 类型安全: 使用TypeScript接口定义数据结构
避坑指南
- 未初始化: 使用前必须调用init()
- 忘记flush: 不flush数据不会保存到磁盘
- 类型转换: get()返回的是联合类型,需要类型断言
- 并发问题: 多处同时修改可能导致数据覆盖
- 存储大小: Preferences适合小数据,大数据用数据库
效果展示
存储的数据文件位置:
/data/storage/el2/base/preferences/app_settings
数据格式:
{
"settings": "{\"theme\":\"auto\",\"themeColorId\":\"orange\",\"fontSize\":\"medium\",\"customAmounts\":[100,200,500,600,1000]}"
}
在HarmonyOS Next中,使用Preferences进行轻量级数据存储的步骤如下:
- 导入模块:
import { preferences } from '@kit.ArkData'。 - 获取Preferences实例:通过
preferences.getPreferences(context, 'YourFileName')获取。 - 存储数据:使用
put()方法,如preferences.put('key', value),然后调用flush()保存。 - 读取数据:使用
get()方法,如preferences.get('key', defaultValue)。 - 删除数据:使用
delete()方法,如preferences.delete('key')。 - 数据持久化:所有操作后需调用
flush()或flushSync()同步到文件。
在HarmonyOS Next中,使用Preferences进行轻量级数据存储主要涉及以下步骤:
-
获取Preferences实例:通过
PreferencesHelper.getPreferences()方法获取指定文件名的Preferences对象,用于后续的数据读写操作。 -
数据存储:使用
putString()、putInt()、putBoolean()等方法存储基本数据类型。所有修改需通过flush()或commit()提交到文件。 -
数据读取:通过
getString()、getInt()、getBoolean()等方法读取已存储的数据,可设置默认值。
对于复杂对象的序列化处理:
- 将对象转换为JSON字符串(如使用
JSON.stringify()),再以字符串形式存储到Preferences。 - 读取时获取JSON字符串,通过反序列化(如
JSON.parse())还原为对象。
注意事项:
- Preferences适用于少量键值对数据,大量数据建议使用关系型数据库。
- 存储复杂对象时,需确保对象可序列化,避免循环引用。
- 异步操作推荐使用
flush(),同步操作使用commit()。

