在鸿蒙应用开发中,数据持久化是实现用户状态保存、本地数据管理的核心能力。对于 3-9 个月经验的初级开发者而言,掌握轻量级的 Preferences 和关系型的 RelationalStore 是处理本地数据的基础。本文将从两种存储方案的核心特性、API 使用入手,结合「用户登录缓存 + 历史记录存储」的实战场景,详解鸿蒙本地数据持久化的实现方式,代码可直接复用。
一、轻量级存储:Preferences(键值对存储)
1. 核心概念与适用场景
Preferences 是鸿蒙提供的轻量级键值对存储工具,基于 XML 文件实现,适合存储简单配置信息(如用户登录状态、字体大小、主题设置等)。其特点为:
- 存储数据类型有限:支持 string、number、boolean、Array等基础类型;
- 操作简单:基于键值对读写,无需复杂的表结构设计;
- 性能高效:适合小数据量(建议单文件不超过 100KB)的频繁读写。
2. 核心 API 使用
(1)获取 Preferences 实例
需通过dataPreferences.createPreferences方法获取,指定存储文件名(自定义)和是否加密(默认 false):
typescript
运行
import dataPreferences from '@ohos.data.preferences';
// 全局声明Preferences实例
let preferences: dataPreferences.Preferences | null = null;
// 初始化Preferences
async function initPreferences() {
try {
preferences = await dataPreferences.createPreferences(getContext(), 'user_info', false);
console.log('Preferences初始化成功');
} catch (err) {
console.error('Preferences初始化失败:', err);
}
}
(2)数据写入(保存登录状态)
使用put方法写入数据,flush方法将数据持久化到文件:
typescript
运行
// 保存用户登录信息
async function saveUserLoginInfo(userId: string, userName: string, isLogin: boolean) {
if (!preferences) return;
try {
await preferences.put('userId', userId);
await preferences.put('userName', userName);
await preferences.put('isLogin', isLogin);
await preferences.flush(); // 强制持久化
console.log('登录信息保存成功');
} catch (err) {
console.error('登录信息保存失败:', err);
}
}
(3)数据读取(获取登录状态)
使用get方法读取数据,需指定默认值(当键不存在时返回):
typescript
运行
// 获取用户登录状态
async function getUserLoginStatus() {
if (!preferences) return { isLogin: false, userId: '', userName: '' };
try {
const isLogin = await preferences.get('isLogin', false);
const userId = await preferences.get('userId', '');
const userName = await preferences.get('userName', '');
return { isLogin, userId, userName };
} catch (err) {
console.error('登录状态读取失败:', err);
return { isLogin: false, userId: '', userName: '' };
}
}
(4)数据删除(退出登录)
使用delete方法删除指定键,或clear方法清空所有数据:
typescript
运行
// 退出登录,清除登录信息
async function clearUserLoginInfo() {
if (!preferences) return;
try {
await preferences.delete('userId');
await preferences.delete('userName');
await preferences.put('isLogin', false);
await preferences.flush();
console.log('登录信息已清除');
} catch (err) {
console.error('登录信息清除失败:', err);
}
}
二、关系型存储:RelationalStore(结构化数据存储)
1. 核心概念与适用场景
RelationalStore 是鸿蒙基于 SQLite 实现的关系型数据库,支持结构化数据的存储与复杂查询,适合存储有关联的批量数据(如用户操作历史、商品列表、聊天记录等)。其特点为:
- 支持 SQL 语法:可通过 SQL 语句或 ORM 方式操作数据;
- 表结构化:需预先定义表结构,支持主键、索引、约束等;
- 事务支持:可处理多表关联、批量数据操作的原子性。
2. 表结构设计与数据库初始化
(1)定义历史记录表结构
以「用户操作历史记录」为例,设计表结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 主键(自增) |
| userId | TEXT | 关联用户 ID |
| action | TEXT | 操作行为(如 “登录”“查看详情”) |
| time | INTEGER | 操作时间(时间戳) |
(2)初始化 RelationalStore 数据库
需创建数据库配置、表结构,并获取数据库实例:
typescript
运行
import relationalStore from '@ohos.data.relationalStore';
// 数据库名称
const DB_NAME = 'user_history.db';
// 数据库版本号
const DB_VERSION = 1;
// 表名
const TABLE_NAME = 'history';
// 创建表的SQL语句
const CREATE_TABLE_SQL = `
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
userId TEXT NOT NULL,
action TEXT NOT NULL,
time INTEGER NOT NULL
);
`;
// 获取数据库实例
async function getRdbStore() {
const config = {
name: DB_NAME,
version: DB_VERSION,
encrypt: false,
createTables: CREATE_TABLE_SQL
};
try {
const rdbStore = await relationalStore.getRdbStore(getContext(), config);
console.log('RelationalStore初始化成功');
return rdbStore;
} catch (err) {
console.error('RelationalStore初始化失败:', err);
return null;
}
}
3. CRUD 操作(历史记录管理)
(1)插入数据(添加操作历史)
typescript
运行
// 添加操作历史
async function addHistoryRecord(userId: string, action: string) {
const rdbStore = await getRdbStore();
if (!rdbStore) return;
try {
const values = new relationalStore.ValuesBucket();
values.putString('userId', userId);
values.putString('action', action);
values.putLong('time', Date.now());
// 插入数据
const rowId = await rdbStore.insert(TABLE_NAME, values);
console.log('历史记录添加成功,行ID:', rowId);
} catch (err) {
console.error('历史记录添加失败:', err);
}
}
(2)查询数据(获取用户操作历史)
typescript
运行
// 获取指定用户的操作历史
async function getHistoryRecords(userId: string) {
const rdbStore = await getRdbStore();
if (!rdbStore) return [];
try {
// 构建查询条件
const predicates = new relationalStore.RdbPredicates(TABLE_NAME);
predicates.equalTo('userId', userId);
predicates.orderByDesc('time'); // 按时间倒序
// 执行查询
const records = await rdbStore.query(predicates, ['id', 'action', 'time']);
// 解析查询结果
const historyList: Array<{ id: number; action: string; time: number }> = [];
while (records.goToNextRow()) {
historyList.push({
id: records.getLong(0),
action: records.getString(1),
time: records.getLong(2)
});
}
records.close(); // 关闭结果集
console.log('历史记录查询成功,共', historyList.length, '条');
return historyList;
} catch (err) {
console.error('历史记录查询失败:', err);
return [];
}
}
(3)删除数据(清空指定用户历史)
typescript
运行
// 清空指定用户的操作历史
async function clearHistoryRecords(userId: string) {
const rdbStore = await getRdbStore();
if (!rdbStore) return;
try {
const predicates = new relationalStore.RdbPredicates(TABLE_NAME);
predicates.equalTo('userId', userId);
const count = await rdbStore.delete(predicates);
console.log('历史记录删除成功,共删除', count, '条');
} catch (err) {
console.error('历史记录删除失败:', err);
}
}
三、实战整合:用户登录缓存 + 历史记录存储
1. 业务流程梳理
- 应用启动时,初始化 Preferences 和 RelationalStore;
- 用户登录成功后,通过 Preferences 保存登录状态,通过 RelationalStore 添加 “登录” 操作历史;
- 应用首页读取 Preferences 的登录状态,未登录则跳转登录页,已登录则查询 RelationalStore 的操作历史并展示;
- 用户退出登录时,清除 Preferences 的登录信息,可选择是否保留历史记录。
2. 核心整合代码示例
typescript
运行
// 应用启动初始化
async function appInit() {
await initPreferences(); // 初始化Preferences
await getRdbStore(); // 初始化RelationalStore
// 检查登录状态
const { isLogin, userId, userName } = await getUserLoginStatus();
if (isLogin) {
console.log('用户已登录:', userName);
// 添加登录历史
await addHistoryRecord(userId, '登录应用');
// 查询并展示历史记录
const historyList = await getHistoryRecords(userId);
console.log('用户操作历史:', historyList);
} else {
console.log('用户未登录,跳转登录页');
}
}
// 模拟用户登录操作
async function userLogin(userId: string, userName: string) {
await saveUserLoginInfo(userId, userName, true);
await addHistoryRecord(userId, '登录应用');
}
// 模拟用户退出登录操作
async function userLogout(userId: string) {
await clearUserLoginInfo();
await addHistoryRecord(userId, '退出登录');
}
四、常见问题与解决方案
1. Preferences 数据未持久化
- 需调用
flush方法强制将内存数据写入文件(默认情况下,鸿蒙会在合适时机自动持久化,但主动调用更可靠); - 检查存储文件名是否包含特殊字符(建议仅使用字母、数字、下划线)。
2. RelationalStore 表创建失败
- 检查 SQL 语句语法是否正确(如字段类型、括号匹配、分号结尾);
- 数据库版本号更新后,需处理表结构升级(可在
onUpgrade回调中实现)。
3. 数据读取权限问题
- 确保在
config.json中声明ohos.permission.WRITE_USER_DATA和ohos.permission.READ_USER_DATA权限:
json
{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.WRITE_USER_DATA"
},
{
"name": "ohos.permission.READ_USER_DATA"
}
]
}
}
五、进阶学习方向
- 数据加密:Preferences 和 RelationalStore 均支持加密存储,可通过
encrypt参数开启,结合鸿蒙的安全模块实现敏感数据加密; - 数据库迁移:处理 RelationalStore 版本升级时的表结构变更、数据迁移逻辑;
- 异步操作优化:使用 Promise、async/await 优化数据操作的异步流程,避免 UI 线程阻塞;
- 分布式数据存储:学习鸿蒙的 DistributedDataAbility,实现多设备间的数据同步。