Harmony学习之本地数据存储
Harmony学习之本地数据存储
一、场景引入
小明在上一篇文章中学会了网络请求,现在他需要将用户登录信息、应用配置、商品收藏等数据持久化保存到本地,这样即使应用重启或网络断开,用户也能看到自己的个性化设置和历史数据。本篇文章将系统讲解HarmonyOS的本地数据存储机制,帮助小明实现数据的本地持久化。
二、本地数据存储方案对比
HarmonyOS提供了多种本地数据存储方式,每种方式都有其适用场景:
| 存储方式 | 适用场景 | 特点 |
|---|---|---|
| Preferences | 用户配置、登录状态、开关设置 | 轻量级键值对存储,类似SharedPreferences |
| 关系型数据库 | 结构化数据、复杂查询、事务支持 | 基于SQLite,支持ACID事务 |
| 文件存储 | 大文件、图片、文档 | 支持二进制流和文本操作 |
三、Preferences轻量级存储
1. 核心概念
Preferences是HarmonyOS提供的轻量级键值对存储方案,适合存储用户配置、应用设置等小数据量信息。数据以Key-Value形式存储,支持字符串、数字、布尔值等基本数据类型。
2. 基本使用
// src/main/ets/common/StorageUtil.ts
import preferences from '@ohos.data.preferences';
export class StorageUtil {
private static instance: StorageUtil;
private preferences: preferences.Preferences | null = null;
// 获取Preferences实例
public static async getInstance(): Promise<StorageUtil> {
if (!StorageUtil.instance) {
StorageUtil.instance = new StorageUtil();
await StorageUtil.instance.init();
}
return StorageUtil.instance;
}
// 初始化Preferences
private async init() {
try {
this.preferences = await preferences.getPreferences(
globalThis.getContext(),
'app_config'
);
} catch (error) {
console.error('初始化Preferences失败:', error);
}
}
// 保存数据
public async save(key: string, value: any): Promise<boolean> {
if (!this.preferences) return false;
try {
await this.preferences.put(key, value);
await this.preferences.flush(); // 持久化到文件
return true;
} catch (error) {
console.error('保存数据失败:', error);
return false;
}
}
// 读取数据
public async get<T>(key: string, defaultValue: T): Promise<T> {
if (!this.preferences) return defaultValue;
try {
return await this.preferences.get(key, defaultValue);
} catch (error) {
console.error('读取数据失败:', error);
return defaultValue;
}
}
// 删除数据
public async delete(key: string): Promise<boolean> {
if (!this.preferences) return false;
try {
await this.preferences.delete(key);
await this.preferences.flush();
return true;
} catch (error) {
console.error('删除数据失败:', error);
return false;
}
}
}
3. 实战应用:保存用户登录状态
// src/main/ets/pages/Login.ets
import { StorageUtil } from '../common/StorageUtil';
@Entry
@Component
struct Login {
@State username: string = '';
@State password: string = '';
build() {
Column({ space: 20 }) {
// ... 登录表单UI代码
Button('登录')
.onClick(() => {
this.handleLogin();
})
}
}
// 处理登录
private async handleLogin() {
// 验证用户名密码...
// 保存登录状态
const storage = await StorageUtil.getInstance();
await storage.save('isLoggedIn', true);
await storage.save('username', this.username);
// 跳转到首页
router.replaceUrl({ url: 'pages/Home' });
}
}
四、关系型数据库存储
1. 核心概念
关系型数据库基于SQLite组件,提供结构化数据存储能力,支持复杂的查询、事务、索引等功能。适合存储用户信息、商品数据、订单记录等结构化数据。
2. 数据库创建与表定义
// src/main/ets/database/DatabaseHelper.ts
import relationalStore from '@ohos.data.relationalStore';
// 用户表定义
export interface User {
id?: number;
name: string;
email: string;
age: number;
createTime: number;
}
export class DatabaseHelper {
private static instance: DatabaseHelper;
private rdbStore: relationalStore.RdbStore | null = null;
// 数据库配置
private readonly DB_NAME = 'app_database.db';
private readonly DB_VERSION = 1;
// 创建用户表SQL
private readonly CREATE_USER_TABLE = `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER,
createTime INTEGER DEFAULT (strftime('%s', 'now'))
)
`;
// 获取单例实例
public static async getInstance(): Promise<DatabaseHelper> {
if (!DatabaseHelper.instance) {
DatabaseHelper.instance = new DatabaseHelper();
await DatabaseHelper.instance.init();
}
return DatabaseHelper.instance;
}
// 初始化数据库
private async init() {
try {
const context = globalThis.getContext();
const storeConfig: relationalStore.StoreConfig = {
name: this.DB_NAME,
securityLevel: relationalStore.SecurityLevel.S1
};
this.rdbStore = await relationalStore.getRdbStore(context, storeConfig);
// 创建表
await this.rdbStore.executeSql(this.CREATE_USER_TABLE);
console.log('数据库初始化成功');
} catch (error) {
console.error('数据库初始化失败:', error);
}
}
}
3. 增删改查操作
// 在DatabaseHelper类中继续添加方法
// 插入用户
public async insertUser(user: User): Promise<number> {
if (!this.rdbStore) return -1;
try {
const valueBucket: relationalStore.ValuesBucket = {
'name': user.name,
'email': user.email,
'age': user.age
};
const rowId = await this.rdbStore.insert('users', valueBucket);
return rowId;
} catch (error) {
console.error('插入用户失败:', error);
return -1;
}
}
// 查询用户
public async queryUsers(): Promise<User[]> {
if (!this.rdbStore) return [];
try {
const predicates = new relationalStore.RdbPredicates('users');
const columns = ['id', 'name', 'email', 'age', 'createTime'];
const resultSet = await this.rdbStore.query(predicates, columns);
const users: User[] = [];
while (resultSet.goToNextRow()) {
users.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
email: resultSet.getString(resultSet.getColumnIndex('email')),
age: resultSet.getLong(resultSet.getColumnIndex('age')),
createTime: resultSet.getLong(resultSet.getColumnIndex('createTime'))
});
}
resultSet.close();
return users;
} catch (error) {
console.error('查询用户失败:', error);
return [];
}
}
// 更新用户
public async updateUser(user: User): Promise<boolean> {
if (!this.rdbStore || !user.id) return false;
try {
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('id', user.id);
const valueBucket: relationalStore.ValuesBucket = {
'name': user.name,
'email': user.email,
'age': user.age
};
const affectedRows = await this.rdbStore.update(valueBucket, predicates);
return affectedRows > 0;
} catch (error) {
console.error('更新用户失败:', error);
return false;
}
}
// 删除用户
public async deleteUser(id: number): Promise<boolean> {
if (!this.rdbStore) return false;
try {
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('id', id);
const affectedRows = await this.rdbStore.delete(predicates);
return affectedRows > 0;
} catch (error) {
console.error('删除用户失败:', error);
return false;
}
}
4. 实战应用:用户管理
// src/main/ets/pages/UserList.ets
import { DatabaseHelper, User } from '../database/DatabaseHelper';
@Entry
@Component
struct UserList {
@State users: User[] = [];
aboutToAppear() {
this.loadUsers();
}
build() {
Column() {
List() {
ForEach(this.users, (user: User) => {
ListItem() {
Column() {
Text(user.name)
.fontSize(18)
Text(user.email)
.fontSize(14)
.fontColor(Color.Gray)
}
.padding(10)
}
})
}
.layoutWeight(1)
}
}
// 加载用户列表
private async loadUsers() {
const dbHelper = await DatabaseHelper.getInstance();
this.users = await dbHelper.queryUsers();
}
}
五、文件存储
1. 核心概念
文件存储适用于保存图片、文档、大体积数据等二进制内容。HarmonyOS提供了文件系统API,支持文件的创建、读写、删除等操作。
2. 文件操作示例
// src/main/ets/common/FileUtil.ts
import fs from '@ohos.file.fs';
export class FileUtil {
// 写入文件
public static async writeFile(filePath: string, content: string): Promise<boolean> {
try {
const file = await fs.open(filePath, fs.OpenMode.CREATE | fs.OpenMode.WRITE);
await fs.write(file.fd, content);
await fs.close(file.fd);
return true;
} catch (error) {
console.error('写入文件失败:', error);
return false;
}
}
// 读取文件
public static async readFile(filePath: string): Promise<string> {
try {
const file = await fs.open(filePath, fs.OpenMode.READ_ONLY);
const stat = await fs.stat(filePath);
const buffer = new ArrayBuffer(stat.size);
await fs.read(file.fd, buffer);
await fs.close(file.fd);
const textDecoder = new util.TextDecoder();
return textDecoder.decode(buffer);
} catch (error) {
console.error('读取文件失败:', error);
return '';
}
}
// 获取应用私有目录
public static getFilesDir(): string {
const context = globalThis.getContext();
return context.filesDir;
}
}
六、最佳实践
1. 数据存储选型指南
Preferences适用场景:
- 用户配置信息(主题、语言、字体大小)
- 登录状态、Token等敏感信息
- 简单的开关设置
关系型数据库适用场景:
- 用户信息、商品列表等结构化数据
- 需要复杂查询、排序、分页的场景
- 需要事务支持的业务数据
文件存储适用场景:
- 图片、视频、文档等大文件
- 日志文件、缓存数据
- 需要导出/导入的数据
2. 性能优化建议
Preferences优化:
- 批量操作时先put再flush,减少IO次数
- 避免存储大JSON对象,建议使用数据库
- 及时清理不再使用的数据
数据库优化:
- 为常用查询字段创建索引
- 使用事务处理批量操作
- 避免在主线程执行耗时查询
文件存储优化:
- 大文件使用流式读写
- 定期清理缓存文件
- 使用临时目录存储临时文件
3. 错误处理与调试
// 完整的错误处理示例
try {
const dbHelper = await DatabaseHelper.getInstance();
const users = await dbHelper.queryUsers();
// 处理数据...
} catch (error) {
console.error('数据库操作失败:', error);
promptAction.showToast({
message: '数据加载失败,请稍后重试',
duration: 2000
});
}
七、总结与行动建议
核心要点回顾
- Preferences:轻量级键值对存储,适合配置信息
- 关系型数据库:结构化数据存储,支持复杂查询
- 文件存储:大文件、二进制数据存储
- 选型原则:根据数据特点和业务需求选择合适的存储方案
行动建议
- 动手实践:创建用户配置页面,使用Preferences保存主题设置
- 数据库实战:实现一个简单的待办事项应用,使用数据库存储任务数据
- 文件操作:实现图片缓存功能,将网络图片保存到本地
- 性能优化:为数据库查询添加索引,优化查询性能
通过本篇文章的学习,你已经掌握了HarmonyOS本地数据存储的核心能力。下一篇文章将深入讲解列表渲染与性能优化,帮助你实现高效的数据展示和交互体验。

浙公网安备 33010602011771号