HarmonyOS 5开发从入门到精通(八):本地数据存储与持久化
HarmonyOS 5开发从入门到精通(八):本地数据存储与持久化
数据持久化是移动应用开发的核心能力,确保应用数据在设备重启或应用关闭后仍能保留。HarmonyOS 5提供了多种数据持久化方案,从轻量级的键值对存储到复杂的关系型数据库,满足不同场景的需求。本篇将深入讲解本地数据存储的实现、优化和实战应用。
一、数据持久化方案概览
1.1 三种主要存储方式对比
| 特性 | Preferences | KV-Store | RelationalStore |
|---|---|---|---|
| 数据模型 | 键值对 | 键值对 | 关系型表 |
| 查询能力 | 简单 | 简单 | 复杂SQL查询 |
| 适合数据量 | <1MB | <10MB | 无限制 |
| 跨设备同步 | 不支持 | 支持 | 支持 |
| 事务支持 | 不支持 | 有限支持 | 完整支持 |
选择建议:
- 用户配置:Preferences
- 应用缓存:KV-Store
- 结构化业务数据:RelationalStore
- 需要跨设备同步的数据:KV-Store或RelationalStore
二、用户首选项(Preferences)
2.1 基本使用
Preferences是最轻量级的键值对存储方案,适合保存少量配置信息。
import preferences from '@ohos.data.preferences';
import { BusinessError } from '@ohos.base';
// 创建Preferences实例
let prefs: preferences.Preferences | null = null;
async function initPreferences() {
try {
const context = getContext(this);
prefs = await preferences.getPreferences(context, 'user_settings');
console.info('Preferences初始化成功');
} catch (error) {
console.error(`Preferences初始化失败: ${(error as BusinessError).message}`);
}
}
// 存储数据
async function saveData(key: string, value: string) {
if (!prefs) return;
await prefs.put(key, value);
await prefs.flush(); // 持久化到文件
}
// 读取数据
async function getData(key: string, defaultValue: string = ''): Promise<string> {
if (!prefs) return defaultValue;
return await prefs.get(key, defaultValue);
}
2.2 封装工具类
// utils/preferences.ts
import preferences from '@ohos.data.preferences';
import { BusinessError } from '@ohos.base';
class PreferencesManager {
private static instance: PreferencesManager;
private prefs: preferences.Preferences | null = null;
private context: any;
static getInstance(context: any): PreferencesManager {
if (!PreferencesManager.instance) {
PreferencesManager.instance = new PreferencesManager(context);
}
return PreferencesManager.instance;
}
private constructor(context: any) {
this.context = context;
}
async init(storeName: string = 'default'): Promise<void> {
try {
this.prefs = await preferences.getPreferences(this.context, storeName);
} catch (error) {
console.error(`Preferences初始化失败: ${(error as BusinessError).message}`);
}
}
async setString(key: string, value: string): Promise<void> {
if (!this.prefs) return;
await this.prefs.put(key, value);
await this.prefs.flush();
}
async getString(key: string, defaultValue: string = ''): Promise<string> {
if (!this.prefs) return defaultValue;
return await this.prefs.get(key, defaultValue);
}
async setNumber(key: string, value: number): Promise<void> {
await this.setString(key, value.toString());
}
async getNumber(key: string, defaultValue: number = 0): Promise<number> {
const value = await this.getString(key);
return value ? parseInt(value) : defaultValue;
}
async setBoolean(key: string, value: boolean): Promise<void> {
await this.setString(key, value ? 'true' : 'false');
}
async getBoolean(key: string, defaultValue: boolean = false): Promise<boolean> {
const value = await this.getString(key);
return value ? value === 'true' : defaultValue;
}
async remove(key: string): Promise<void> {
if (!this.prefs) return;
await this.prefs.delete(key);
await this.prefs.flush();
}
async clear(): Promise<void> {
if (!this.prefs) return;
await this.prefs.clear();
await this.prefs.flush();
}
}
export default PreferencesManager;
三、关系型数据库(RelationalStore)
3.1 数据库创建与表结构定义
import relationalStore from '@ohos.data.relationalStore';
import { BusinessError } from '@ohos.base';
// 定义表结构
const SQL_CREATE_TABLE = `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
age INTEGER,
created_at INTEGER DEFAULT (strftime('%s', 'now'))
)
`;
// 数据库配置
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'app_database.db',
securityLevel: relationalStore.SecurityLevel.S2,
encrypt: true
};
class DatabaseManager {
private rdbStore: relationalStore.RdbStore | null = null;
private context: any;
constructor(context: any) {
this.context = context;
}
async init(): Promise<void> {
try {
this.rdbStore = await relationalStore.getRdbStore(this.context, STORE_CONFIG);
await this.rdbStore.executeSql(SQL_CREATE_TABLE);
console.info('数据库初始化成功');
} catch (error) {
console.error(`数据库初始化失败: ${(error as BusinessError).message}`);
}
}
// 插入数据
async insertUser(name: string, email: string, age: number): Promise<number> {
if (!this.rdbStore) return -1;
const valuesBucket: relationalStore.ValuesBucket = {
'name': name,
'email': email,
'age': age
};
try {
const result = await this.rdbStore.insert('users', valuesBucket);
return result;
} catch (error) {
console.error(`插入数据失败: ${(error as BusinessError).message}`);
return -1;
}
}
// 查询数据
async queryUsers(): Promise<any[]> {
if (!this.rdbStore) return [];
const predicates = new relationalStore.RdbPredicates('users');
const columns = ['id', 'name', 'email', 'age', 'created_at'];
try {
const resultSet = await this.rdbStore.query(predicates, columns);
const users: any[] = [];
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')),
created_at: resultSet.getLong(resultSet.getColumnIndex('created_at'))
});
}
resultSet.close();
return users;
} catch (error) {
console.error(`查询数据失败: ${(error as BusinessError).message}`);
return [];
}
}
// 更新数据
async updateUser(id: number, name: string, email: string, age: number): Promise<number> {
if (!this.rdbStore) return 0;
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('id', id);
const valuesBucket: relationalStore.ValuesBucket = {
'name': name,
'email': email,
'age': age
};
try {
const result = await this.rdbStore.update(valuesBucket, predicates);
return result;
} catch (error) {
console.error(`更新数据失败: ${(error as BusinessError).message}`);
return 0;
}
}
// 删除数据
async deleteUser(id: number): Promise<number> {
if (!this.rdbStore) return 0;
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('id', id);
try {
const result = await this.rdbStore.delete(predicates);
return result;
} catch (error) {
console.error(`删除数据失败: ${(error as BusinessError).message}`);
return 0;
}
}
// 事务操作
async executeTransaction(operations: (() => Promise<void>)[]): Promise<void> {
if (!this.rdbStore) return;
try {
await this.rdbStore.beginTransaction();
for (const operation of operations) {
await operation();
}
await this.rdbStore.commit();
} catch (error) {
await this.rdbStore.rollBack();
console.error(`事务执行失败: ${(error as BusinessError).message}`);
throw error;
}
}
}
export default DatabaseManager;
3.2 复杂查询示例
// 条件查询
async function queryUsersByCondition(): Promise<any[]> {
if (!this.rdbStore) return [];
const predicates = new relationalStore.RdbPredicates('users');
predicates.equalTo('age', 25) // age = 25
.greaterThan('created_at', Date.now() - 7 * 24 * 60 * 60 * 1000) // 最近7天
.orderByAsc('name') // 按姓名升序
.limit(10); // 限制10条
const columns = ['id', 'name', 'email', 'age'];
try {
const resultSet = await this.rdbStore.query(predicates, columns);
const users: any[] = [];
while (resultSet.goToNextRow()) {
users.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
email: resultSet.getString(resultSet.ColumnIndex('email')),
age: resultSet.getLong(resultSet.getColumnIndex('age'))
});
}
resultSet.close();
return users;
} catch (error) {
console.error(`条件查询失败: ${(error as BusinessError).message}`);
return [];
}
}
// 聚合查询
async function getStatistics(): Promise<any> {
if (!this.rdbStore) return null;
const sql = `
SELECT
COUNT(*) as total_users,
AVG(age) as avg_age,
MAX(age) as max_age,
MIN(age) as min_age
FROM users
`;
try {
const resultSet = await this.rdbStore.executeSql(sql);
const stats: any = {};
if (resultSet.goToNextRow()) {
stats.total_users = resultSet.getLong(resultSet.getColumnIndex('total_users'));
stats.avg_age = resultSet.getDouble(resultSet.getColumnIndex('avg_age'));
stats.max_age = resultSet.getLong(resultSet.getColumnIndex('max_age'));
stats.min_age = resultSet.getLong(resultSet.getColumnIndex('min_age'));
}
resultSet.close();
return stats;
} catch (error) {
console.error(`聚合查询失败: ${(error as BusinessError).message}`);
return null;
}
}
四、文件存储(FileIO)
4.1 文件读写操作
import fileio from '@ohos.fileio';
import { BusinessError } from '@ohos.base';
class FileManager {
private context: any;
constructor(context: any) {
this.context = context;
}
// 写入文本文件
async writeTextFile(filePath: string, content: string): Promise<boolean> {
try {
const fd = await fileio.open(filePath, fileio.OpenMode.CREATE | fileio.OpenMode.WRITE_ONLY);
const buffer = new ArrayBuffer(content.length * 2);
const encoder = new TextEncoder();
const encoded = encoder.encode(content);
await fileio.write(fd, encoded.buffer, { offset: 0 });
await fileio.close(fd);
return true;
} catch (error) {
console.error(`写入文件失败: ${(error as BusinessError).message}`);
return false;
}
}
// 读取文本文件
async readTextFile(filePath: string): Promise<string> {
try {
const fd = await fileio.open(filePath, fileio.OpenMode.READ_ONLY);
const stat = await fileio.stat(fd);
const buffer = new ArrayBuffer(stat.size);
await fileio.read(fd, buffer, { offset: 0 });
await fileio.close(fd);
const decoder = new TextDecoder('utf-8');
return decoder.decode(new Uint8Array(buffer));
} catch (error) {
console.error(`读取文件失败: ${(error as BusinessError).message}`);
return '';
}
}
// 创建目录
async createDirectory(dirPath: string): Promise<boolean> {
try {
await fileio.mkdir(dirPath);
return true;
} catch (error) {
console.error(`创建目录失败: ${(error as BusinessError).message}`);
return false;
}
}
// 检查文件是否存在
async fileExists(filePath: string): Promise<boolean> {
try {
await fileio.access(filePath);
return true;
} catch (error) {
return false;
}
}
// 删除文件
async deleteFile(filePath: string): Promise<boolean> {
try {
await fileio.unlink(filePath);
return true;
} catch (error) {
console.error(`删除文件失败: ${(error as BusinessError).message}`);
return false;
}
}
// 获取文件列表
async listFiles(dirPath: string): Promise<string[]> {
try {
const files = await fileio.listFile(dirPath);
return files;
} catch (error) {
console.error(`获取文件列表失败: ${(error as BusinessError).message}`);
return [];
}
}
}
export default FileManager;
4.2 文件缓存管理
// utils/fileCache.ts
import fileio from '@ohos.fileio';
import { BusinessError } from '@ohos.base';
interface CacheItem {
key: string;
value: string;
timestamp: number;
ttl: number; // 缓存有效时间(毫秒)
}
class FileCacheManager {
private cacheDir: string;
private memoryCache: Map<string, CacheItem> = new Map();
constructor(context: any) {
this.cacheDir = context.cacheDir + '/file_cache';
this.initCacheDir();
}
private async initCacheDir(): Promise<void> {
try {
await fileio.mkdir(this.cacheDir);
} catch (error) {
// 目录已存在或其他错误
}
}
// 设置缓存
async set(key: string, value: string, ttl: number = 24 * 60 * 60 * 1000): Promise<void> {
const cacheItem: CacheItem = {
key,
value,
timestamp: Date.now(),
ttl
};
// 内存缓存
this.memoryCache.set(key, cacheItem);
// 文件缓存
const filePath = `${this.cacheDir}/${key}.json`;
const content = JSON.stringify(cacheItem);
try {
const fd = await fileio.open(filePath, fileio.OpenMode.CREATE | fileio.OpenMode.WRITE_ONLY);
const encoder = new TextEncoder();
const encoded = encoder.encode(content);
await fileio.write(fd, encoded.buffer, { offset: 0 });
await fileio.close(fd);
} catch (error) {
console.error(`缓存写入失败: ${(error as BusinessError).message}`);
}
}
// 获取缓存
async get(key: string): Promise<string | null> {
// 检查内存缓存
const memoryItem = this.memoryCache.get(key);
if (memoryItem && Date.now() - memoryItem.timestamp < memoryItem.ttl) {
return memoryItem.value;
}
// 检查文件缓存
const filePath = `${this.cacheDir}/${key}.json`;
try {
const fd = await fileio.open(filePath, fileio.OpenMode.READ_ONLY);
const stat = await fileio.stat(fd);
const buffer = new ArrayBuffer(stat.size);
await fileio.read(fd, buffer, { offset: 0 });
await fileio.close(fd);
const decoder = new TextDecoder('utf-8');
const content = decoder.decode(new Uint8Array(buffer));
const cacheItem: CacheItem = JSON.parse(content);
// 检查是否过期
if (Date.now() - cacheItem.timestamp > cacheItem.ttl) {
await this.delete(key);
return null;
}
// 更新内存缓存
this.memoryCache.set(key, cacheItem);
return cacheItem.value;
} catch (error) {
return null;
}
}
// 删除缓存
async delete(key: string): Promise<void> {
this.memoryCache.delete(key);
const filePath = `${this.cacheDir}/${key}.json`;
try {
await fileio.unlink(filePath);
} catch (error) {
// 文件不存在或其他错误
}
}
// 清理过期缓存
async cleanup(): Promise<void> {
try {
const files = await fileio.listFile(this.cacheDir);
for (const file of files) {
const filePath = `${this.cacheDir}/${file}`;
const fd = await fileio.open(filePath, fileio.OpenMode.READ_ONLY);
const stat = await fileio.stat(fd);
const buffer = new ArrayBuffer(stat.size);
await fileio.read(fd, buffer, { offset: 0 });
await fileio.close(fd);
const decoder = new TextDecoder('utf-8');
const content = decoder.decode(new Uint8Array(buffer));
const cacheItem: CacheItem = JSON.parse(content);
if (Date.now() - cacheItem.timestamp > cacheItem.ttl) {
await fileio.unlink(filePath);
}
}
} catch (error) {
console.error(`清理缓存失败: ${(error as BusinessError).message}`);
}
}
}
export default FileCacheManager;
五、数据加密与安全
5.1 敏感数据加密存储
import huks from '@ohos.UniversalKeystoreKit';
import { util } from '@ohos.ArkTS';
import { BusinessError } from '@ohos.base';
class EncryptionManager {
private keyAlias: string = 'app_encryption_key';
// 生成加密密钥
async generateKey(): Promise<void> {
const properties: huks.HuksParam[] = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
},
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
}
];
const options: huks.HuksOptions = { properties };
try {
await huks.generateKeyItem(this.keyAlias, options);
console.info('加密密钥生成成功');
} catch (error) {
console.error(`加密密钥生成失败: ${(error as BusinessError).message}`);
}
}
// 加密数据
async encryptData(data: string): Promise<string> {
const properties: huks.HuksParam[] = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
},
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
},
{
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksPadding.HUKS_PADDING_PKCS7
},
{
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksBlockMode.HUKS_BLOCK_MODE_CBC
}
];
const encoder = new TextEncoder();
const inData = encoder.encode(data);
const options: huks.HuksOptions = {
properties,
inData
};
try {
const handleObj = await huks.initSession(this.keyAlias, options);
const result = await huks.finishSession(handleObj.handle, options);
const base64Helper = new util.Base64Helper();
return base64Helper.encodeToStringSync(result.outData as Uint8Array);
} catch (error) {
console.error(`数据加密失败: ${(error as BusinessError).message}`);
throw error;
}
}
// 解密数据
async decryptData(encryptedData: string): Promise<string> {
const properties: huks.HuksParam[] = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
},
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
},
{
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksPadding.HUKS_PADDING_PKCS7
},
{
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksBlockMode.HUKS_BLOCK_MODE_CBC
}
];
const base64Helper = new util.Base64Helper();
const inData = base64Helper.decodeSync(encryptedData);
const options: huks.HuksOptions = {
properties,
inData
};
try {
const handleObj = await huks.initSession(this.keyAlias, options);
const result = await huks.finishSession(handleObj.handle, options);
const decoder = new TextDecoder('utf-8');
return decoder.decode(result.outData as Uint8Array);
} catch (error) {
console.error(`数据解密失败: ${(error as BusinessError).message}`);
throw error;
}
}
}
export default EncryptionManager;
5.2 安全的用户首选项存储
// utils/securePreferences.ts
import PreferencesManager from './preferences';
import EncryptionManager from './encryptionManager';
class SecurePreferencesManager {
private preferences: PreferencesManager;
private encryption: EncryptionManager;
constructor(context: any) {
this.preferences = PreferencesManager.getInstance(context);
this.encryption = new EncryptionManager();
}
async init(): Promise<void> {
await this.preferences.init('secure_store');
await this.encryption.generateKey();
}
async setSecureString(key: string, value: string): Promise<void> {
const encryptedValue = await this.encryption.encryptData(value);
await this.preferences.setString(key, encryptedValue);
}
async getSecureString(key: string, defaultValue: string = ''): Promise<string> {
const encryptedValue = await this.preferences.getString(key);
if (!encryptedValue) return defaultValue;
try {
return await this.encryption.decryptData(encryptedValue);
} catch (error) {
console.error(`解密数据失败: ${(error as BusinessError).message}`);
return defaultValue;
}
}
async setSecureNumber(key: string, value: number): Promise<void> {
await this.setSecureString(key, value.toString());
}
async getSecureNumber(key: string, defaultValue: number = 0): Promise<number> {
const value = await this.getSecureString(key);
return value ? parseInt(value) : defaultValue;
}
}
export default SecurePreferencesManager;
六、数据迁移与升级
6.1 数据库版本升级
// 数据库升级回调
const onUpgrade = async (rdbStore: relationalStore.RdbStore, oldVersion: number, newVersion: number) => {
console.info(`数据库升级: ${oldVersion} -> ${newVersion}`);
try {
// 版本1到版本2的升级
if (oldVersion < 2) {
await rdbStore.executeSql('ALTER TABLE users ADD COLUMN avatar TEXT');
}
// 版本2到版本3的升级
if (oldVersion < 3) {
await rdbStore.executeSql('CREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT)');
}
// 版本3到版本4的升级
if (oldVersion < 4) {
await rdbStore.executeSql('ALTER TABLE users ADD COLUMN last_login INTEGER DEFAULT 0');
}
} catch (error) {
console.error(`数据库升级失败: ${(error as BusinessError).message}`);
throw error;
}
};
// 数据库配置
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'app_database.db',
securityLevel: relationalStore.SecurityLevel.S2,
encrypt: true
};
// 初始化数据库
async function initDatabase(context: any): Promise<relationalStore.RdbStore | null> {
try {
const rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG);
// 设置数据库版本
await rdbStore.setVersion(4);
// 设置升级回调
await rdbStore.setUpgradeCallback(onUpgrade);
return rdbStore;
} catch (error) {
console.error(`数据库初始化失败: ${(error as BusinessError).message}`);
return null;
}
}
6.2 数据备份与恢复
// utils/backupManager.ts
import fileio from '@ohos.fileio';
import { BusinessError } from '@ohos.base';
class BackupManager {
private context: any;
private backupDir: string;
constructor(context: any) {
this.context = context;
this.backupDir = this.context.filesDir + '/backups';
}
// 创建备份
async createBackup(sourceDir: string, backupName: string): Promise<boolean> {
try {
const backupPath = `${this.backupDir}/${backupName}`;
await fileio.mkdir(backupPath);
const files = await fileio.listFile(sourceDir);
for (const file of files) {
const sourcePath = `${sourceDir}/${file}`;
const targetPath = `${backupPath}/${file}`;
await this.copyFile(sourcePath, targetPath);
}
return true;
} catch (error) {
console.error(`创建备份失败: ${(error as BusinessError).message}`);
return false;
}
}
// 恢复备份
async restoreBackup(backupName: string, targetDir: string): Promise<boolean> {
try {
const backupPath = `${this.backupDir}/${backupName}`;
if (!await fileio.access(backupPath)) {
console.error('备份不存在');
return false;
}
const files = await fileio.listFile(backupPath);
for (const file of files) {
const sourcePath = `${backupPath}/${file}`;
const targetPath = `${targetDir}/${file}`;
await this.copyFile(sourcePath, targetPath);
}
return true;
} catch (error) {
console.error(`恢复备份失败: ${(error as BusinessError).message}`);
return false;
}
}
// 复制文件
private async copyFile(sourcePath: string, targetPath: string): Promise<void> {
try {
const sourceFd = await fileio.open(sourcePath, fileio.OpenMode.READ_ONLY);
const targetFd = await fileio.open(targetPath, fileio.OpenMode.CREATE | fileio.OpenMode.WRITE_ONLY);
const stat = await fileio.stat(sourceFd);
const buffer = new ArrayBuffer(stat.size);
await fileio.read(sourceFd, buffer, { offset: 0 });
await fileio.write(targetFd, buffer, { offset: 0 });
await fileio.close(sourceFd);
await fileio.close(targetFd);
} catch (error) {
console.error(`复制文件失败: ${(error as BusinessError).message}`);
throw error;
}
}
// 获取备份列表
async listBackups(): Promise<string[]> {
try {
await fileio.mkdir(this.backupDir);
return await fileio.listFile(this.backupDir);
} catch (error) {
console.error(`获取备份列表失败: ${(error as BusinessError).message}`);
return [];
}
}
// 删除备份
async deleteBackup(backupName: string): Promise<boolean> {
try {
const backupPath = `${this.backupDir}/${backupName}`;
await fileio.rmdir(backupPath);
return true;
} catch (error) {
console.error(`删除备份失败: ${(error as BusinessError).message}`);
return false;
}
}
}
export default BackupManager;
七、实战案例:用户信息管理
7.1 用户信息存储模型
// models/user.ts
export interface User {
id?: number;
username: string;
email: string;
phone?: string;
avatar?: string;
age?: number;
created_at?: number;
updated_at?: number;
}
export interface UserSettings {
theme: string;
language: string;
notifications: boolean;
auto_sync: boolean;
}
7.2 用户服务封装
// services/userService.ts
import DatabaseManager from '../utils/databaseManager';
import PreferencesManager from '../utils/preferencesManager';
import SecurePreferencesManager from '../utils/securePreferencesManager';
import { User, UserSettings } from '../models/user';
class UserService {
private db: DatabaseManager;
private prefs: PreferencesManager;
private securePrefs: SecurePreferencesManager;
constructor(context: any) {
this.db = new DatabaseManager(context);
this.prefs = PreferencesManager.getInstance(context);
this.securePrefs = new SecurePreferencesManager(context);
}
async init(): Promise<void> {
await this.db.init();
await this.prefs.init('user_settings');
await this.securePrefs.init();
}
// 用户注册
async register(user: User): Promise<number> {
return await this.db.insertUser(user.username, user.email, user.age || 0);
}
// 用户登录
async login(username: string, password: string): Promise<boolean> {
// 这里应该是密码验证逻辑,实际应用中需要加密验证
const user = await this.getUserByUsername(username);
if (user) {
// 保存登录状态
await this.prefs.setString('current_user_id', user.id.toString());
await this.prefs.setString('current_username', username);
await this.prefs.setBoolean('is_logged_in', true);
// 保存登录时间
await this.db.updateUserLoginTime(user.id);
return true;
}
return false;
}
// 获取当前用户
async getCurrentUser(): Promise<User | null> {
const userId = await this.prefs.getString('current_user_id');
if (!userId) return null;
return await this.getUserById(parseInt(userId));
}
// 根据ID查询用户
async getUserById(id: number): Promise<User | null> {
const users = await this.db.queryUsers();
return users.find(user => user.id === id) || null;
}
// 根据用户名查询用户
async getUserByUsername(username: string): Promise<User | null> {
const users = await this.db.queryUsers();
return users.find(user => user.username === username) || null;
}
// 更新用户信息
async updateUser(user: User): Promise<boolean> {
if (!user.id) return false;
const result = await this.db.updateUser(
user.id,
user.username,
user.email,
user.age || 0
);
return result > 0;
}
// 删除用户
async deleteUser(id: number): Promise<boolean> {
const result = await this.db.deleteUser(id);
return result > 0;
}
// 获取用户设置
async getUserSettings(): Promise<UserSettings> {
const theme = await this.prefs.getString('theme', 'light');
const language = await this.prefs.getString('language', 'zh-CN');
const notifications = await this.prefs.getBoolean('notifications', true);
const auto_sync = await this.prefs.getBoolean('auto_sync', true);
return {
theme,
language,
notifications,
auto_sync
};
}
// 保存用户设置
async saveUserSettings(settings: UserSettings): Promise<void> {
await this.prefs.setString('theme', settings.theme);
await this.prefs.setString('language', settings.language);
await this.prefs.setBoolean('notifications', settings.notifications);
await this.prefs.setBoolean('auto_sync', settings.auto_sync);
}
// 保存敏感信息(如Token)
async saveToken(token: string): Promise<void> {
await this.securePrefs.setSecureString('auth_token', token);
}
// 获取敏感信息
async getToken(): Promise<string> {
return await this.securePrefs.getSecureString('auth_token', '');
}
// 退出登录
async logout(): Promise<void> {
await this.prefs.remove('current_user_id');
await this.prefs.remove('current_username');
await this.prefs.setBoolean('is_logged_in', false);
await this.securePrefs.delete('auth_token');
}
}
export default UserService;
八、性能优化与最佳实践
8.1 数据库性能优化
// 批量插入数据
async function batchInsertUsers(users: User[]): Promise<void> {
if (!this.rdbStore) return;
try {
await this.rdbStore.beginTransaction();
for (const user of users) {
const valuesBucket: relationalStore.ValuesBucket = {
'name': user.username,
'email': user.email,
'age': user.age || 0
};
await this.rdbStore.insert('users', valuesBucket);
}
await this.rdbStore.commit();
} catch (error) {
await this.rdbStore.rollBack();
console.error(`批量插入失败: ${(error as BusinessError).message}`);
throw error;
}
}
// 使用索引优化查询
async function createIndexes(): Promise<void> {
if (!this.rdbStore) return;
try {
// 为email字段创建索引
await this.rdbStore.executeSql('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)');
// 为created_at字段创建索引
await this.rdbStore.executeSql('CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at)');
console.info('索引创建成功');
} catch (error) {
console.error(`索引创建失败: ${(error as BusinessError).message}`);
}
}
// 分页查询
async function queryUsersWithPagination(page: number, pageSize: number): Promise<any[]> {
if (!this.rdbStore) return [];
const predicates = new relationalStore.RdbPredicates('users');
const columns = ['id', 'name', 'email', 'age', 'created_at'];
predicates.orderByDesc('created_at')
.limit(pageSize)
.offset((page - 1) * pageSize);
try {
const resultSet = await this.rdbStore.query(predicates, columns);
const users: any[] = [];
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')),
created_at: resultSet.getLong(resultSet.getColumnIndex('created_at'))
});
}
resultSet.close();
return users;
} catch (error) {
console.error(`分页查询失败: ${(error as BusinessError).message}`);
return [];
}
}
8.2 内存缓存优化
// utils/cacheManager.ts
interface CacheItem<T> {
data: T;
timestamp: number;
ttl: number;
}
class CacheManager<T> {
private cache: Map<string, CacheItem<T>> = new Map();
private maxSize: number = 100; // 最大缓存数量
// 设置缓存
set(key: string, data: T, ttl: number = 5 * 60 * 1000): void {
if (this.cache.size >= this.maxSize) {
this.evictOldest();
}
this.cache.set(key, {
data,
timestamp: Date.now(),
ttl
});
}
// 获取缓存
get(key: string): T | null {
const item = this.cache.get(key);
if (!item) return null;
// 检查是否过期
if (Date.now() - item.timestamp > item.ttl) {
this.cache.delete(key);
return null;
}
return item.data;
}
// 删除缓存
delete(key: string): void {
this.cache.delete(key);
}
// 清理过期缓存
cleanup(): void {
const now = Date.now();
for (const [key, item] of this.cache.entries()) {
if (now - item.timestamp > item.ttl) {
this.cache.delete(key);
}
}
}
// 清理所有缓存
clear(): void {
this.cache.clear();
}
// 淘汰最旧的缓存
private evictOldest(): void {
let oldestKey: string | null = null;
let oldestTime = Infinity;
for (const [key, item] of this.cache.entries()) {
if (item.timestamp < oldestTime) {
oldestTime = item.timestamp;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
}
export default CacheManager;
8.3 数据访问层封装
// services/dataService.ts
import DatabaseManager from '../utils/databaseManager';
import CacheManager from '../utils/cacheManager';
class DataService {
private db: DatabaseManager;
private userCache: CacheManager<any>;
private settingsCache: CacheManager<any>;
constructor(context: any) {
this.db = new DatabaseManager(context);
this.userCache = new CacheManager();
this.settingsCache = new CacheManager();
}
async init(): Promise<void> {
await this.db.init();
}
// 获取用户信息(带缓存)
async getUserById(id: number): Promise<any> {
const cacheKey = `user_${id}`;
const cachedUser = this.userCache.get(cacheKey);
if (cachedUser) {
return cachedUser;
}
const user = await this.db.getUserById(id);
if (user) {
this.userCache.set(cacheKey, user, 30 * 60 * 1000); // 缓存30分钟
}
return user;
}
// 批量获取用户信息
async getUsersByIds(ids: number[]): Promise<any[]> {
const users: any[] = [];
const missingIds: number[] = [];
// 先尝试从缓存获取
for (const id of ids) {
const cacheKey = `user_${id}`;
const cachedUser = this.userCache.get(cacheKey);
if (cachedUser) {
users.push(cachedUser);
} else {
missingIds.push(id);
}
}
// 批量查询缺失的用户
if (missingIds.length > 0) {
const dbUsers = await this.db.getUsersByIds(missingIds);
for (const user of dbUsers) {
const cacheKey = `user_${user.id}`;
this.userCache.set(cacheKey, user, 30 * 60 * 1000);
users.push(user);
}
}
return users;
}
// 更新用户信息(同时更新缓存)
async updateUser(user: any): Promise<boolean> {
const result = await this.db.updateUser(user);
if (result) {
const cacheKey = `user_${user.id}`;
this.userCache.set(cacheKey, user, 30 * 60 * 1000);
}
return result;
}
// 清除用户缓存
clearUserCache(id?: number): void {
if (id) {
const cacheKey = `user_${id}`;
this.userCache.delete(cacheKey);
} else {
this.userCache.clear();
}
}
}
export default DataService;
九、总结
通过本篇学习,您已经掌握了:
✅ Preferences存储:轻量级键值对存储,适合用户配置和简单数据
✅ 关系型数据库:复杂结构化数据存储,支持SQL查询和事务操作
✅ 文件存储:大文件读写和管理,支持文本和二进制数据
✅ 数据加密:敏感信息的安全存储,使用AES等加密算法
✅ 数据迁移:数据库版本升级和数据备份恢复
✅ 性能优化:缓存机制、批量操作和索引优化
关键知识点回顾:
- Preferences适合存储少量配置信息,使用简单但功能有限
- 关系型数据库支持复杂查询和事务,适合业务数据存储
- 文件存储适合大文件和二进制数据,需要手动管理
- 敏感数据必须加密存储,使用系统提供的加密库
- 数据库升级需要处理版本迁移,确保数据一致性
- 使用缓存和批量操作可以显著提升性能
最佳实践建议:
- 根据数据量选择合适的存储方案
- 敏感数据必须加密存储
- 数据库操作使用事务保证数据一致性
- 使用缓存减少数据库访问次数
- 定期清理过期数据和缓存
- 实现数据备份和恢复机制
下一篇我们将学习分布式数据管理,掌握如何在多设备间同步数据,实现跨设备无缝体验。
浙公网安备 33010602011771号