Harmony之路:数据持久化——Preferences本地存储方案
Harmony之路:数据持久化——Preferences本地存储方案
一、引入:为什么需要数据持久化?
在移动应用开发中,我们经常需要保存用户的配置信息、登录状态、应用数据等,这些数据需要在应用关闭后仍然保留。HarmonyOS提供了Preferences作为轻量级数据存储方案,它采用键值对的方式存储数据,支持多种数据类型,适合存储小量、简单的数据。掌握Preferences的使用,是构建完整应用的必要技能。
二、讲解:Preferences的核心用法
1. Preferences基础操作
Preferences提供了类似键值对的存储机制,支持字符串、数字、布尔值、数组等多种数据类型的存储和读取。
基础数据操作示例:
import preferences from '@ohos.data.preferences';
// 获取Preferences实例
const context = getContext(this) as common.UIAbilityContext;
const preferences = await preferences.getPreferences(context, 'myAppData');
// 设置数据
await preferences.put('username', '张三');
await preferences.put('userAge', 25);
await preferences.put('isLogin', false);
await preferences.put('lastLoginTime', Date.now());
// 获取数据
const username = await preferences.get('username', '');
const userAge = await preferences.get('userAge', 0);
const isLogin = await preferences.get('isLogin', false);
const lastLoginTime = await preferences.get('lastLoginTime', 0);
console.log('用户信息:', username, userAge, isLogin, new Date(lastLoginTime));
// 检查是否存在
const hasUsername = await preferences.has('username');
console.log('是否存在username:', hasUsername);
// 删除数据
await preferences.delete('username');
// 清空所有数据
await preferences.clear();
2. 数据同步与异步操作
Preferences提供了同步和异步两种操作方式,推荐使用异步操作避免阻塞UI线程。
同步操作示例:
// 同步获取Preferences实例
const preferences = preferences.getPreferencesSync(context, 'myAppData');
// 同步设置数据
preferences.putSync('key', 'value');
// 同步获取数据
const value = preferences.getSync('key', 'default');
// 同步删除数据
preferences.deleteSync('key');
// 同步清空
preferences.clearSync();
异步操作示例(推荐):
// 异步获取Preferences实例
const preferences = await preferences.getPreferences(context, 'myAppData');
// 异步设置数据
await preferences.put('key', 'value');
// 异步获取数据
const value = await preferences.get('key', 'default');
// 异步删除数据
await preferences.delete('key');
// 异步清空
await preferences.clear();
3. 存储复杂数据类型
Preferences支持存储对象和数组等复杂数据类型,但需要先转换为JSON字符串。
对象存储示例:
class UserInfo {
name: string;
age: number;
email: string;
constructor(name: string, age: number, email: string) {
this.name = name;
this.age = age;
this.email = email;
}
}
// 存储对象
const user = new UserInfo('张三', 25, 'zhangsan@example.com');
await preferences.put('userInfo', JSON.stringify(user));
// 读取对象
const userStr = await preferences.get('userInfo', '');
if (userStr) {
const userInfo: UserInfo = JSON.parse(userStr);
console.log('用户信息:', userInfo.name, userInfo.age, userInfo.email);
}
数组存储示例:
// 存储数组
const todoList = ['学习ArkTS', '掌握Preferences', '完成项目'];
await preferences.put('todoList', JSON.stringify(todoList));
// 读取数组
const todoStr = await preferences.get('todoList', '');
if (todoStr) {
const todos: string[] = JSON.parse(todoStr);
console.log('待办事项:', todos);
}
4. 数据变化监听
Preferences支持监听数据变化,当指定键的值发生变化时触发回调。
数据变化监听示例:
// 添加数据变化监听
const dataChangeListener: preferences.DataChangeListener = {
onDataChange: (key: string) => {
console.log(`数据发生变化: ${key}`);
// 重新读取数据
this.loadData();
}
};
// 注册监听
preferences.on('dataChange', dataChangeListener);
// 取消监听
preferences.off('dataChange', dataChangeListener);
5. 实际应用场景
场景1:用户登录状态管理
class UserService {
private static preferences: preferences.Preferences;
// 初始化Preferences
static async init(context: common.UIAbilityContext) {
this.preferences = await preferences.getPreferences(context, 'userData');
}
// 保存用户信息
static async saveUserInfo(user: UserInfo) {
await this.preferences.put('userInfo', JSON.stringify(user));
await this.preferences.put('isLogin', true);
await this.preferences.put('lastLoginTime', Date.now());
}
// 获取用户信息
static async getUserInfo(): Promise<UserInfo | null> {
const userStr = await this.preferences.get('userInfo', '');
return userStr ? JSON.parse(userStr) : null;
}
// 检查登录状态
static async isLogin(): Promise<boolean> {
return await this.preferences.get('isLogin', false);
}
// 退出登录
static async logout() {
await this.preferences.delete('userInfo');
await this.preferences.put('isLogin', false);
}
}
// 在应用入口初始化
@Entry
@Component
struct MainPage {
async aboutToAppear() {
const context = getContext(this) as common.UIAbilityContext;
await UserService.init(context);
}
build() {
// 页面内容
}
}
场景2:应用配置管理
class AppConfig {
private static preferences: preferences.Preferences;
// 配置项键名
private static readonly KEYS = {
THEME: 'theme',
LANGUAGE: 'language',
NOTIFICATION: 'notification',
SOUND: 'sound'
};
static async init(context: common.UIAbilityContext) {
this.preferences = await preferences.getPreferences(context, 'appConfig');
}
// 保存主题配置
static async setTheme(theme: string) {
await this.preferences.put(this.KEYS.THEME, theme);
}
// 获取主题配置
static async getTheme(): Promise<string> {
return await this.preferences.get(this.KEYS.THEME, 'light');
}
// 保存语言配置
static async setLanguage(language: string) {
await this.preferences.put(this.KEYS.LANGUAGE, language);
}
// 获取语言配置
static async getLanguage(): Promise<string> {
return await this.preferences.get(this.KEYS.LANGUAGE, 'zh-CN');
}
// 保存通知设置
static async setNotification(enabled: boolean) {
await this.preferences.put(this.KEYS.NOTIFICATION, enabled);
}
// 获取通知设置
static async getNotification(): Promise<boolean> {
return await this.preferences.get(this.KEYS.NOTIFICATION, true);
}
// 保存声音设置
static async setSound(enabled: boolean) {
await this.preferences.put(this.KEYS.SOUND, enabled);
}
// 获取声音设置
static async getSound(): Promise<boolean> {
return await this.preferences.get(this.KEYS.SOUND, true);
}
}
场景3:历史记录管理
class HistoryManager {
private static preferences: preferences.Preferences;
private static readonly MAX_HISTORY = 10;
static async init(context: common.UIAbilityContext) {
this.preferences = await preferences.getPreferences(context, 'searchHistory');
}
// 添加搜索历史
static async addSearchHistory(keyword: string) {
let history: string[] = await this.getSearchHistory();
// 移除重复项
history = history.filter(item => item !== keyword);
// 添加到开头
history.unshift(keyword);
// 限制数量
if (history.length > this.MAX_HISTORY) {
history = history.slice(0, this.MAX_HISTORY);
}
await this.preferences.put('searchHistory', JSON.stringify(history));
}
// 获取搜索历史
static async getSearchHistory(): Promise<string[]> {
const historyStr = await this.preferences.get('searchHistory', '');
return historyStr ? JSON.parse(historyStr) : [];
}
// 清空搜索历史
static async clearSearchHistory() {
await this.preferences.delete('searchHistory');
}
}
6. 性能优化与最佳实践
1. 合理使用Preferences
- 适合存储小量、简单的配置数据
- 不适合存储大量数据或频繁读写的数据
- 对于大量数据,应该使用关系型数据库(如RDB)
2. 数据加密
对于敏感数据,应该进行加密存储:
import cryptoFramework from '@ohos.security.cryptoFramework';
// 加密数据
async function encryptData(data: string, key: string): Promise<string> {
// 使用cryptoFramework进行加密
// 具体实现略
return encryptedData;
}
// 解密数据
async function decryptData(encryptedData: string, key: string): Promise<string> {
// 使用cryptoFramework进行解密
// 具体实现略
return decryptedData;
}
// 存储加密数据
const sensitiveData = '敏感信息';
const encrypted = await encryptData(sensitiveData, 'mySecretKey');
await preferences.put('sensitiveData', encrypted);
// 读取解密数据
const encryptedData = await preferences.get('sensitiveData', '');
if (encryptedData) {
const decrypted = await decryptData(encryptedData, 'mySecretKey');
console.log('解密数据:', decrypted);
}
3. 数据备份与恢复
实现数据备份功能:
class DataBackup {
private static preferences: preferences.Preferences;
static async init(context: common.UIAbilityContext) {
this.preferences = await preferences.getPreferences(context, 'appData');
}
// 导出数据
static async exportData(): Promise<string> {
const allData = await this.preferences.getAll();
return JSON.stringify(allData);
}
// 导入数据
static async importData(data: string) {
const dataObj = JSON.parse(data);
for (const [key, value] of Object.entries(dataObj)) {
await this.preferences.put(key, value);
}
}
// 重置数据
static async resetData() {
await this.preferences.clear();
}
}
4. 错误处理
为Preferences操作添加错误处理:
class SafePreferences {
private preferences: preferences.Preferences;
constructor(context: common.UIAbilityContext, name: string) {
this.preferences = preferences.getPreferencesSync(context, name);
}
async put(key: string, value: preferences.ValueType): Promise<boolean> {
try {
await this.preferences.put(key, value);
return true;
} catch (error) {
console.error('保存数据失败:', error);
return false;
}
}
async get(key: string, defaultValue: preferences.ValueType): Promise<preferences.ValueType> {
try {
return await this.preferences.get(key, defaultValue);
} catch (error) {
console.error('读取数据失败:', error);
return defaultValue;
}
}
async delete(key: string): Promise<boolean> {
try {
await this.preferences.delete(key);
return true;
} catch (error) {
console.error('删除数据失败:', error);
return false;
}
}
}
三、总结:数据持久化的核心要点
✅ 核心知识点回顾
- Preferences是轻量级存储:采用键值对方式存储数据,适合小量、简单的配置数据
- 支持多种数据类型:字符串、数字、布尔值、数组、对象(需JSON序列化)
- 同步与异步操作:提供同步和异步两种操作方式,推荐使用异步操作
- 数据变化监听:可以监听指定键的数据变化
- 数据加密:敏感数据应该进行加密存储
⚠️ 常见问题与解决方案
- 数据丢失:确保在应用启动时初始化Preferences,避免在异步操作完成前读取数据
- 类型错误:读取数据时指定正确的默认值类型,避免类型转换错误
- 性能问题:避免频繁读写大量数据,对于大量数据应该使用关系型数据库
- 数据安全:敏感数据必须进行加密存储,避免明文存储
🎯 最佳实践建议
- 合理使用:Preferences适合存储配置信息、用户设置等小量数据
- 封装管理:将Preferences操作封装到服务类中,提高代码可维护性
- 错误处理:为所有Preferences操作添加错误处理,避免应用崩溃
- 数据备份:实现数据备份和恢复功能,提高用户体验
下一步预告:在第十一篇中,我们将学习网络请求,掌握使用HTTP模块进行网络数据交互的方法,实现应用与服务器的数据通信。

浙公网安备 33010602011771号