当前位置: 首页 > news >正文

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;// 初始化Preferencesstatic 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;}}
}

三、总结:数据持久化的核心要点

✅ 核心知识点回顾

  1. Preferences是轻量级存储:采用键值对方式存储数据,适合小量、简单的配置数据
  2. 支持多种数据类型:字符串、数字、布尔值、数组、对象(需JSON序列化)
  3. 同步与异步操作:提供同步和异步两种操作方式,推荐使用异步操作
  4. 数据变化监听:可以监听指定键的数据变化
  5. 数据加密:敏感数据应该进行加密存储

⚠️ 常见问题与解决方案

  1. 数据丢失:确保在应用启动时初始化Preferences,避免在异步操作完成前读取数据
  2. 类型错误:读取数据时指定正确的默认值类型,避免类型转换错误
  3. 性能问题:避免频繁读写大量数据,对于大量数据应该使用关系型数据库
  4. 数据安全:敏感数据必须进行加密存储,避免明文存储

🎯 最佳实践建议

  1. 合理使用:Preferences适合存储配置信息、用户设置等小量数据
  2. 封装管理:将Preferences操作封装到服务类中,提高代码可维护性
  3. 错误处理:为所有Preferences操作添加错误处理,避免应用崩溃
  4. 数据备份:实现数据备份和恢复功能,提高用户体验

下一步预告:在第十一篇中,我们将学习网络请求,掌握使用HTTP模块进行网络数据交互的方法,实现应用与服务器的数据通信。

http://www.jsqmd.com/news/130775/

相关文章:

  • 【Java】异常
  • 【Java】异常
  • Harmony之路:页面的舞台——Ability与页面路由的奥秘
  • 如何优化微信个人号的API二次开发流程?
  • 震惊!想找靠谱艺术漆品牌?联系方法竟藏在这!
  • 为什么偏偏是周二?一文了解微软“补丁星期二”的前世今生
  • Harmony之路:列表的艺术——List与ForEach高效渲染
  • python学习day05
  • 基于java的SpringBoot/SSM+Vue+uniapp的高校智能考试系统的详细设计和实现(源码+lw+部署文档+讲解等)
  • C++与浏览器交织-从Chrome插件到WebAssembly,开启性能之门
  • C++与浏览器交织-从Chrome插件到WebAssembly,开启性能之门
  • Harmony之路:让界面活起来——@State状态管理初体验
  • Harmony之路:组件间对话——@Prop与@Link通信机制
  • 基于大数据的二手交易推荐系统的详细设计和实现(源码+lw+部署文档+讲解等)
  • 为什么tcp要用mss
  • 利用clip-retrieval自动化收集图像并用于模型引导
  • 华为云服务器,使用Centos7.9安装docker
  • C++高并发编程核心技能解析
  • Harmony之路:全局状态管家——AppStorage与应用级数据管理
  • Harmony之路:UI构建之基石——ArkUI声明式组件与布局
  • Harmony之路:认识新语言——ArkTS语法快速入门
  • oracle 12c(12.1) acfs文件在线缩小问题
  • 32 岁 IT 运维踩坑:甲方突然不续约,项目解散,我成了失业大军一员
  • 代码重构艺术
  • YOLOv11改进 - C3k2融合 | C3k2融合 IIA信息整合注意力(Information Integration Attention )平衡精度与计算成本 | TGRS2025
  • 打造贷前风控“防火墙”:基于天远数据借贷风险API的用户画像构建实战
  • 模块化智能革命:Deepoc开发板如何成为智慧厨房的“万能AI引擎”
  • 跨境热销游戏手柄爆款密码
  • Harmony之路:初探鸿蒙——HarmonyOS 5与开发环境搭建
  • 多模态数据中台为什么说是被“逼出来”的?