存储系统 #
一、存储方案概述 #
1.1 存储类型对比 #
| 存储方案 | 容量 | 持久化 | 适用场景 |
|---|---|---|---|
| Preferences | 小量 | 是 | 配置、设置 |
| 文件系统 | 大量 | 是 | 文件、缓存 |
| SQLite | 大量 | 是 | 结构化数据 |
| IndexedDB | 大量 | 是 | Web端大数据 |
| 内存存储 | 中量 | 否 | 临时数据 |
二、Preferences插件 #
2.1 安装 #
bash
npm install @capacitor/preferences
npx cap sync
2.2 基本使用 #
typescript
import { Preferences } from '@capacitor/preferences';
// 存储数据
await Preferences.set({
key: 'username',
value: 'john_doe'
});
// 读取数据
const { value } = await Preferences.get({ key: 'username' });
console.log(value); // 'john_doe'
// 删除数据
await Preferences.remove({ key: 'username' });
// 清空所有数据
await Preferences.clear();
// 获取所有键
const { keys } = await Preferences.keys();
console.log(keys); // ['key1', 'key2', ...]
2.3 存储对象 #
typescript
// 存储对象
async function setObject<T>(key: string, value: T): Promise<void> {
await Preferences.set({
key,
value: JSON.stringify(value)
});
}
// 读取对象
async function getObject<T>(key: string): Promise<T | null> {
const { value } = await Preferences.get({ key });
return value ? JSON.parse(value) : null;
}
// 使用示例
interface User {
id: string;
name: string;
email: string;
}
await setObject<User>('user', {
id: '1',
name: 'John',
email: 'john@example.com'
});
const user = await getObject<User>('user');
2.4 封装存储服务 #
typescript
// src/services/storage.service.ts
import { Preferences } from '@capacitor/preferences';
class StorageService {
private prefix = 'app_';
async set<T>(key: string, value: T): Promise<void> {
await Preferences.set({
key: `${this.prefix}${key}`,
value: JSON.stringify(value)
});
}
async get<T>(key: string, defaultValue?: T): Promise<T | undefined> {
const { value } = await Preferences.get({
key: `${this.prefix}${key}`
});
if (value === null) {
return defaultValue;
}
try {
return JSON.parse(value) as T;
} catch {
return value as unknown as T;
}
}
async remove(key: string): Promise<void> {
await Preferences.remove({
key: `${this.prefix}${key}`
});
}
async clear(): Promise<void> {
const { keys } = await Preferences.keys();
for (const key of keys) {
if (key.startsWith(this.prefix)) {
await Preferences.remove({ key });
}
}
}
async has(key: string): Promise<boolean> {
const { value } = await Preferences.get({
key: `${this.prefix}${key}`
});
return value !== null;
}
}
export const storageService = new StorageService();
三、文件系统插件 #
3.1 安装 #
bash
npm install @capacitor/filesystem
npx cap sync
3.2 权限配置 #
Android (AndroidManifest.xml):
xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3.3 基本操作 #
typescript
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
// 写入文件
async function writeFile() {
await Filesystem.writeFile({
path: 'mydir/myfile.txt',
data: 'Hello, Capacitor!',
directory: Directory.Documents,
encoding: Encoding.UTF8
});
}
// 读取文件
async function readFile() {
const result = await Filesystem.readFile({
path: 'mydir/myfile.txt',
directory: Directory.Documents,
encoding: Encoding.UTF8
});
console.log(result.data); // 'Hello, Capacitor!'
}
// 删除文件
async function deleteFile() {
await Filesystem.deleteFile({
path: 'mydir/myfile.txt',
directory: Directory.Documents
});
}
// 检查文件是否存在
async function fileExists() {
try {
await Filesystem.stat({
path: 'mydir/myfile.txt',
directory: Directory.Documents
});
return true;
} catch {
return false;
}
}
3.4 目录操作 #
typescript
import { Filesystem, Directory } from '@capacitor/filesystem';
// 创建目录
async function createDirectory() {
await Filesystem.mkdir({
path: 'mydir/subdir',
directory: Directory.Documents,
recursive: true // 递归创建
});
}
// 删除目录
async function removeDirectory() {
await Filesystem.rmdir({
path: 'mydir',
directory: Directory.Documents,
recursive: true // 递归删除
});
}
// 列出目录内容
async function listDirectory() {
const result = await Filesystem.readdir({
path: 'mydir',
directory: Directory.Documents
});
console.log(result.files);
// [{ name: 'file1.txt', type: 'file' }, { name: 'subdir', type: 'directory' }]
}
3.5 存储目录 #
typescript
enum Directory {
Documents, // 文档目录
Data, // 应用数据目录
Cache, // 缓存目录
External, // 外部存储(Android)
ExternalStorage // 外部存储根目录(Android)
}
3.6 文件URI操作 #
typescript
// 获取文件URI
async function getFileUri() {
const result = await Filesystem.getUri({
path: 'mydir/myfile.txt',
directory: Directory.Documents
});
console.log(result.uri);
// iOS: file:///var/mobile/Containers/Data/.../mydir/myfile.txt
// Android: file:///data/user/0/com.example.app/files/mydir/myfile.txt
}
// 复制文件
async function copyFile() {
await Filesystem.copy({
from: 'source.txt',
to: 'destination.txt',
directory: Directory.Documents
});
}
// 移动文件
async function moveFile() {
await Filesystem.move({
from: 'oldpath.txt',
to: 'newpath.txt',
directory: Directory.Documents
});
}
3.7 二进制文件 #
typescript
// 写入Base64数据
async function writeBinaryFile(base64Data: string) {
await Filesystem.writeFile({
path: 'image.jpg',
data: base64Data,
directory: Directory.Documents
});
}
// 读取为Base64
async function readBinaryFile() {
const result = await Filesystem.readFile({
path: 'image.jpg',
directory: Directory.Documents
});
// result.data 是Base64字符串
return result.data;
}
四、SQLite数据库 #
4.1 安装社区插件 #
bash
npm install @capacitor-community/sqlite
npx cap sync
4.2 基本使用 #
typescript
import { CapacitorSQLite, SQLiteConnection, SQLiteDBConnection } from '@capacitor-community/sqlite';
const sqlite = new SQLiteConnection(CapacitorSQLite);
// 创建/打开数据库
async function openDatabase(): Promise<SQLiteDBConnection> {
const db = await sqlite.createConnection(
'mydb',
false, // encrypted
'no-encryption',
1 // version
);
await db.open();
return db;
}
// 创建表
async function createTable(db: SQLiteDBConnection) {
await db.execute(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
}
// 插入数据
async function insertUser(db: SQLiteDBConnection, name: string, email: string) {
await db.run(
'INSERT INTO users (name, email) VALUES (?, ?)',
[name, email]
);
}
// 查询数据
async function getUsers(db: SQLiteDBConnection) {
const result = await db.query('SELECT * FROM users');
return result.values;
}
// 更新数据
async function updateUser(db: SQLiteDBConnection, id: number, name: string) {
await db.run(
'UPDATE users SET name = ? WHERE id = ?',
[name, id]
);
}
// 删除数据
async function deleteUser(db: SQLiteDBConnection, id: number) {
await db.run('DELETE FROM users WHERE id = ?', [id]);
}
4.3 封装SQLite服务 #
typescript
// src/services/database.service.ts
import { CapacitorSQLite, SQLiteConnection, SQLiteDBConnection } from '@capacitor-community/sqlite';
class DatabaseService {
private sqlite: SQLiteConnection;
private db: SQLiteDBConnection | null = null;
private dbName = 'app_database';
constructor() {
this.sqlite = new SQLiteConnection(CapacitorSQLite);
}
async init(): Promise<void> {
this.db = await this.sqlite.createConnection(
this.dbName,
false,
'no-encryption',
1
);
await this.db.open();
await this.createTables();
}
private async createTables(): Promise<void> {
if (!this.db) return;
await this.db.execute(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
);
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed INTEGER DEFAULT 0,
user_id INTEGER,
FOREIGN KEY (user_id) REFERENCES users(id)
);
`);
}
async query<T>(sql: string, params: any[] = []): Promise<T[]> {
if (!this.db) throw new Error('Database not initialized');
const result = await this.db.query(sql, params);
return result.values || [];
}
async run(sql: string, params: any[] = []): Promise<{ changes: number; lastId: number }> {
if (!this.db) throw new Error('Database not initialized');
const result = await this.db.run(sql, params);
return {
changes: result.changes?.changes || 0,
lastId: result.changes?.lastId || 0
};
}
async transaction<T>(callback: () => Promise<T>): Promise<T> {
if (!this.db) throw new Error('Database not initialized');
await this.db.execute('BEGIN TRANSACTION');
try {
const result = await callback();
await this.db.execute('COMMIT');
return result;
} catch (error) {
await this.db.execute('ROLLBACK');
throw error;
}
}
async close(): Promise<void> {
if (this.db) {
await this.sqlite.closeConnection(this.dbName, false);
this.db = null;
}
}
}
export const databaseService = new DatabaseService();
五、缓存管理 #
5.1 缓存服务 #
typescript
// src/services/cache.service.ts
import { Preferences } from '@capacitor/preferences';
interface CacheItem<T> {
data: T;
timestamp: number;
ttl: number;
}
class CacheService {
private prefix = 'cache_';
async set<T>(key: string, data: T, ttl: number = 3600000): Promise<void> {
const item: CacheItem<T> = {
data,
timestamp: Date.now(),
ttl
};
await Preferences.set({
key: `${this.prefix}${key}`,
value: JSON.stringify(item)
});
}
async get<T>(key: string): Promise<T | null> {
const { value } = await Preferences.get({
key: `${this.prefix}${key}`
});
if (!value) return null;
const item: CacheItem<T> = JSON.parse(value);
// 检查是否过期
if (Date.now() - item.timestamp > item.ttl) {
await this.remove(key);
return null;
}
return item.data;
}
async remove(key: string): Promise<void> {
await Preferences.remove({
key: `${this.prefix}${key}`
});
}
async clear(): Promise<void> {
const { keys } = await Preferences.keys();
for (const key of keys) {
if (key.startsWith(this.prefix)) {
await Preferences.remove({ key });
}
}
}
async has(key: string): Promise<boolean> {
const data = await this.get(key);
return data !== null;
}
}
export const cacheService = new CacheService();
5.2 使用缓存 #
typescript
// 带缓存的数据获取
async function fetchWithCache<T>(
key: string,
fetcher: () => Promise<T>,
ttl: number = 3600000
): Promise<T> {
// 尝试从缓存获取
const cached = await cacheService.get<T>(key);
if (cached !== null) {
return cached;
}
// 获取新数据
const data = await fetcher();
// 存入缓存
await cacheService.set(key, data, ttl);
return data;
}
// 使用示例
interface User {
id: string;
name: string;
}
async function getUser(id: string): Promise<User> {
return fetchWithCache(
`user_${id}`,
() => fetch(`/api/users/${id}`).then(r => r.json()),
60000 // 1分钟缓存
);
}
六、数据迁移 #
6.1 版本迁移 #
typescript
class DataMigration {
private currentVersion = 1;
async migrate(): Promise<void> {
const { value } = await Preferences.get({ key: 'db_version' });
const version = value ? parseInt(value) : 0;
if (version < 1) {
await this.migrateToV1();
}
// 未来版本迁移
// if (version < 2) {
// await this.migrateToV2();
// }
await Preferences.set({
key: 'db_version',
value: this.currentVersion.toString()
});
}
private async migrateToV1(): Promise<void> {
// V1迁移逻辑
console.log('Migrating to V1...');
}
}
七、完整示例 #
7.1 用户数据管理 #
typescript
// src/services/user-data.service.ts
import { storageService } from './storage.service';
import { cacheService } from './cache.service';
interface UserData {
profile: {
name: string;
email: string;
avatar?: string;
};
settings: {
theme: 'light' | 'dark';
language: string;
notifications: boolean;
};
lastSync: number;
}
class UserDataService {
private readonly PROFILE_KEY = 'user_profile';
private readonly SETTINGS_KEY = 'user_settings';
async getProfile() {
return storageService.get<UserData['profile']>(this.PROFILE_KEY);
}
async setProfile(profile: UserData['profile']): Promise<void> {
await storageService.set(this.PROFILE_KEY, profile);
await cacheService.remove('user_full_data');
}
async getSettings() {
const defaultSettings: UserData['settings'] = {
theme: 'light',
language: 'zh-CN',
notifications: true
};
return storageService.get<UserData['settings']>(
this.SETTINGS_KEY,
defaultSettings
);
}
async updateSettings(settings: Partial<UserData['settings']>): Promise<void> {
const current = await this.getSettings();
await storageService.set(this.SETTINGS_KEY, {
...current,
...settings
});
}
async getFullData(): Promise<UserData> {
return cacheService.get<UserData>('user_full_data') || {
profile: await this.getProfile(),
settings: await this.getSettings(),
lastSync: Date.now()
};
}
async clearAll(): Promise<void> {
await storageService.remove(this.PROFILE_KEY);
await storageService.remove(this.SETTINGS_KEY);
await cacheService.clear();
}
}
export const userDataService = new UserDataService();
八、总结 #
8.1 存储方案选择 #
| 数据类型 | 推荐方案 |
|---|---|
| 配置设置 | Preferences |
| 简单数据 | Preferences |
| 文件/图片 | Filesystem |
| 结构化数据 | SQLite |
| 临时缓存 | 内存/Preferences |
8.2 下一步 #
了解存储系统后,让我们学习 推送通知!
最后更新:2026-03-28