React Native文件操作:本地存储与云存储集成方案
引言:移动应用数据存储的困境与解决方案
在React Native开发中,开发者常常面临数据存储的三重挑战:存储容量限制、跨设备同步和离线访问支持。传统解决方案往往将本地存储与云存储割裂处理,导致代码冗余和数据一致性问题。本文将系统介绍React Native生态中完整的存储解决方案,从基础的本地存储API到企业级云同步架构,帮助开发者构建可靠、高效的数据存储系统。
一、React Native存储生态系统概览
React Native提供了多层次的存储解决方案,从简单的键值对存储到复杂的文件系统操作,每种方案都有其适用场景:
存储方案决策指南
| 存储需求 | 推荐方案 | 数据容量 | 性能特点 | 安全性 |
|---|---|---|---|---|
| 用户偏好设置 | AsyncStorage | <1MB | 毫秒级读取 | 低 |
| 认证令牌 | react-native-keychain | <1KB | 快速访问 | 高 |
| 离线文档 | react-native-fs | 无限制 | 取决于文件大小 | 中 |
| 结构化数据 | Realm | 无限制 | 复杂查询高效 | 中 |
| 跨设备同步 | Firebase Cloud Firestore | 无限制 | 实时同步 | 高 |
二、本地存储实现方案
2.1 AsyncStorage迁移与使用指南
虽然AsyncStorage已从React Native核心库迁移至社区维护(@react-native-async-storage/async-storage),但它仍是轻量级键值存储的首选方案:
安装与配置:
# 使用npm安装
npm install @react-native-async-storage/async-storage
# 使用yarn安装
yarn add @react-native-async-storage/async-storage
# 对于iOS项目
cd ios && pod install && cd ..
基础操作封装:
// storage/AsyncStorageService.js
import AsyncStorage from '@react-native-async-storage/async-storage';
export const StorageService = {
/**
* 存储数据
* @param {string} key - 存储键名
* @param {any} value - 存储值(将被JSON序列化)
* @returns {Promise<void>}
*/
setItem: async (key, value) => {
try {
const jsonValue = JSON.stringify(value);
await AsyncStorage.setItem(key, jsonValue);
} catch (e) {
console.error('AsyncStorage setItem error:', e);
throw new Error(`存储失败: ${e.message}`);
}
},
/**
* 获取数据
* @param {string} key - 存储键名
* @returns {Promise<any>} - 返回解析后的值或null
*/
getItem: async (key) => {
try {
const jsonValue = await AsyncStorage.getItem(key);
return jsonValue != null ? JSON.parse(jsonValue) : null;
} catch (e) {
console.error('AsyncStorage getItem error:', e);
throw new Error(`获取失败: ${e.message}`);
}
},
/**
* 删除数据
* @param {string} key - 存储键名
* @returns {Promise<void>}
*/
removeItem: async (key) => {
try {
await AsyncStorage.removeItem(key);
} catch (e) {
console.error('AsyncStorage removeItem error:', e);
throw new Error(`删除失败: ${e.message}`);
}
},
/**
* 清空所有存储数据
* @returns {Promise<void>}
*/
clear: async () => {
try {
await AsyncStorage.clear();
} catch (e) {
console.error('AsyncStorage clear error:', e);
throw new Error(`清空失败: ${e.message}`);
}
},
/**
* 获取所有键名
* @returns {Promise<string[]>} - 键名数组
*/
getAllKeys: async () => {
try {
return await AsyncStorage.getAllKeys();
} catch (e) {
console.error('AsyncStorage getAllKeys error:', e);
throw new Error(`获取键名失败: ${e.message}`);
}
}
};
使用示例:
// 存储用户设置
await StorageService.setItem('userPreferences', {
theme: 'dark',
notifications: true,
fontSize: 16
});
// 获取用户设置
const prefs = await StorageService.getItem('userPreferences');
console.log('用户主题:', prefs.theme);
// 获取所有存储键
const keys = await StorageService.getAllKeys();
console.log('存储的键名:', keys);
2.2 文件系统操作(react-native-fs)
对于大型文件存储需求,react-native-fs提供了完整的文件系统访问能力:
安装:
npm install react-native-fs --save
核心功能实现:
// storage/FileSystemService.js
import RNFS from 'react-native-fs';
export const FileSystemService = {
/**
* 获取应用沙盒目录路径
* @returns {Promise<string>}
*/
getDocumentDirectory: async () => {
return RNFS.DocumentDirectoryPath;
},
/**
* 写入文件
* @param {string} filename - 文件名
* @param {string} content - 文件内容
* @param {boolean} [append=false] - 是否追加模式
* @returns {Promise<boolean>} - 成功返回true
*/
writeFile: async (filename, content, append = false) => {
const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
return RNFS.writeFile(path, content, 'utf8', append);
},
/**
* 读取文件内容
* @param {string} filename - 文件名
* @returns {Promise<string>} - 文件内容
*/
readFile: async (filename) => {
const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
return RNFS.readFile(path, 'utf8');
},
/**
* 下载文件
* @param {string} url - 下载URL
* @param {string} filename - 保存文件名
* @param {Function} onProgress - 进度回调函数
* @returns {Promise<Object>} - 下载结果
*/
downloadFile: async (url, filename, onProgress) => {
const destinationPath = `${RNFS.DocumentDirectoryPath}/${filename}`;
const downloadOptions = {
fromUrl: url,
toFile: destinationPath,
background: true,
discretionary: true,
progress: (res) => {
const progress = res.bytesWritten / res.contentLength;
onProgress && onProgress(progress);
}
};
try {
const downloadResult = RNFS.downloadFile(downloadOptions).promise;
return downloadResult;
} catch (error) {
console.error('文件下载失败:', error);
throw error;
}
},
/**
* 获取目录下所有文件
* @param {string} [directory=''] - 目录名,默认为文档根目录
* @returns {Promise<Array<Object>>} - 文件列表
*/
readDirectory: async (directory = '') => {
const path = directory
? `${RNFS.DocumentDirectoryPath}/${directory}`
: RNFS.DocumentDirectoryPath;
return RNFS.readDir(path);
},
/**
* 删除文件
* @param {string} filename - 文件名
* @returns {Promise<void>}
*/
deleteFile: async (filename) => {
const path = `${RNFS.DocumentDirectoryPath}/${filename}`;
return RNFS.unlink(path);
}
};
文件下载示例:
// 下载大型PDF文件并显示进度
const downloadLargeFile = async () => {
const fileUrl = 'https://example.com/large-document.pdf';
const fileName = 'offline-document.pdf';
try {
await FileSystemService.downloadFile(
fileUrl,
fileName,
(progress) => {
// 更新进度指示器
setDownloadProgress(Math.round(progress * 100));
}
);
showToast('文件下载完成');
// 下载完成后可以读取文件路径进行预览
const filePath = `${RNFS.DocumentDirectoryPath}/${fileName}`;
openFilePreview(filePath);
} catch (error) {
showToast(`下载失败: ${error.message}`);
}
};
三、云存储集成架构
3.1 REST API数据同步实现
API服务封装:
// api/ApiService.js
import NetInfo from '@react-native-community/netinfo';
export const ApiService = {
/**
* 检查网络连接状态
* @returns {Promise<boolean>} - 是否有网络连接
*/
async isNetworkAvailable() {
const netState = await NetInfo.fetch();
return netState.isConnected && netState.isInternetReachable;
},
/**
* 通用请求方法
* @param {string} endpoint - API端点
* @param {Object} options - 请求选项
* @returns {Promise<Object>} - 响应数据
*/
async request(endpoint, options = {}) {
const baseUrl = 'https://api.yourdomain.com/v1';
const url = `${baseUrl}${endpoint}`;
// 默认请求头
const headers = {
'Content-Type': 'application/json',
...options.headers,
};
// 添加认证令牌
const token = await StorageService.getItem('authToken');
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
try {
const response = await fetch(url, {
method: options.method || 'GET',
headers,
body: options.body ? JSON.stringify(options.body) : undefined,
timeout: options.timeout || 30000,
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.message || `HTTP错误: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`API请求失败 [${endpoint}]:`, error.message);
// 检查网络状态
const isOnline = await this.isNetworkAvailable();
if (!isOnline) {
throw new Error('网络连接不可用,请检查您的网络设置');
}
throw error;
}
},
// 数据模型API
items: {
/**
* 获取项目列表
* @param {Object} params - 查询参数
* @returns {Promise<Array<Object>>} - 项目列表
*/
async getList(params = {}) {
const queryString = new URLSearchParams(params).toString();
return ApiService.request(`/items${queryString ? `?${queryString}` : ''}`);
},
/**
* 获取单个项目详情
* @param {string} id - 项目ID
* @returns {Promise<Object>} - 项目详情
*/
async getById(id) {
return ApiService.request(`/items/${id}`);
},
/**
* 创建新项目
* @param {Object} data - 项目数据
* @returns {Promise<Object>} - 创建的项目
*/
async create(data) {
return ApiService.request('/items', {
method: 'POST',
body: data,
});
},
/**
* 更新项目
* @param {string} id - 项目ID
* @param {Object} data - 更新数据
* @returns {Promise<Object>} - 更新后的项目
*/
async update(id, data) {
return ApiService.request(`/items/${id}`, {
method: 'PUT',
body: data,
});
},
/**
* 删除项目
* @param {string} id - 项目ID
* @returns {Promise<Object>} - 删除结果
*/
async delete(id) {
return ApiService.request(`/items/${id}`, {
method: 'DELETE',
});
},
},
};
3.2 离线优先同步系统设计
同步服务实现:
// sync/SyncService.js
import { StorageService } from '../storage/AsyncStorageService';
import { ApiService } from '../api/ApiService';
import NetInfo from '@react-native-community/netinfo';
export const SyncService = {
/**
* 同步队列存储键
*/
SYNC_QUEUE_KEY: 'offline_sync_queue',
/**
* 上次同步时间存储键
*/
LAST_SYNC_KEY: 'last_sync_timestamp',
/**
* 添加操作到同步队列
* @param {Object} operation - 操作对象
* @param {string} operation.type - 操作类型 (CREATE/UPDATE/DELETE)
* @param {string} operation.entity - 实体类型
* @param {string} [operation.id] - 实体ID (UPDATE/DELETE时必填)
* @param {Object} operation.data - 实体数据
* @returns {Promise<void>}
*/
async queueOperation(operation) {
const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY) || [];
queue.push({
...operation,
timestamp: Date.now(),
uuid: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
});
await StorageService.setItem(this.SYNC_QUEUE_KEY, queue);
},
/**
* 处理同步队列
* @returns {Promise<Object>} - 同步结果
*/
async processQueue() {
// 检查网络连接
const networkState = await NetInfo.fetch();
if (!networkState.isConnected || !networkState.isInternetReachable) {
return { success: false, error: '无网络连接', processed: 0 };
}
const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY) || [];
if (queue.length === 0) {
return { success: true, processed: 0, message: '同步队列为空' };
}
let processedCount = 0;
const failedOperations = [];
// 按时间顺序处理队列
for (const operation of queue) {
try {
switch (operation.type) {
case 'CREATE':
await ApiService[operation.entity].create(operation.data);
break;
case 'UPDATE':
await ApiService[operation.entity].update(operation.id, operation.data);
break;
case 'DELETE':
await ApiService[operation.entity].delete(operation.id);
break;
default:
console.warn('未知操作类型:', operation.type);
failedOperations.push(operation);
continue;
}
processedCount++;
} catch (error) {
console.error(`同步操作失败 [${operation.type} ${operation.entity}]:`, error);
failedOperations.push(operation);
// 对于非致命错误,继续处理后续操作
// 如果是认证错误等严重错误,跳出循环
if (error.message.includes('认证') || error.message.includes('401')) {
failedOperations.push(...queue.slice(processedCount + failedOperations.length));
break;
}
}
}
// 保存失败的操作,用于下次重试
await StorageService.setItem(this.SYNC_QUEUE_KEY, failedOperations);
// 更新最后同步时间
if (processedCount > 0) {
await StorageService.setItem(this.LAST_SYNC_KEY, Date.now());
}
return {
success: failedOperations.length === 0,
processed: processedCount,
failed: failedOperations.length,
message: `${processedCount} 个操作成功, ${failedOperations.length} 个操作失败`
};
},
/**
* 执行完全同步(拉取服务器最新数据)
* @param {string} entity - 实体类型
* @param {Function} onProgress - 进度回调
* @returns {Promise<Object>} - 同步结果
*/
async fullSync(entity, onProgress) {
try {
const lastSyncTime = await StorageService.getItem(this.LAST_SYNC_KEY) || 0;
const result = await ApiService[entity].getList({
updatedSince: lastSyncTime
});
// 保存到本地存储
await StorageService.setItem(`${entity}_list`, result.data);
// 更新最后同步时间
await StorageService.setItem(this.LAST_SYNC_KEY, Date.now());
onProgress && onProgress(100); // 进度100%
return {
success: true,
count: result.data.length,
message: `成功同步 ${result.data.length} 条${entity}数据`
};
} catch (error) {
console.error(`全量同步失败 [${entity}]:`, error);
return {
success: false,
error: error.message
};
}
},
/**
* 初始化同步服务
* @returns {Promise<void>}
*/
async initialize() {
// 检查并创建同步队列(如果不存在)
const queue = await StorageService.getItem(this.SYNC_QUEUE_KEY);
if (!queue) {
await StorageService.setItem(this.SYNC_QUEUE_KEY, []);
}
// 设置网络状态监听
NetInfo.addEventListener(state => {
if (state.isConnected && state.isInternetReachable) {
console.log('网络已连接,尝试同步队列...');
this.processQueue().then(result => {
console.log('后台同步结果:', result);
});
}
});
}
};
同步服务使用流程:
// 在应用启动时初始化同步服务
SyncService.initialize();
// 创建数据时同时添加到同步队列
const createItem = async (data) => {
// 1. 保存到本地存储
const localItems = await StorageService.getItem('items_list') || [];
const newItem = { ...data, id: generateLocalId(), isPendingSync: true };
localItems.push(newItem);
await StorageService.setItem('items_list', localItems);
// 2. 添加到同步队列
await SyncService.queueOperation({
type: 'CREATE',
entity: 'items',
data: newItem
});
// 3. 尝试立即同步(如果在线)
const networkState = await NetInfo.fetch();
if (networkState.isConnected && networkState.isInternetReachable) {
await SyncService.processQueue();
}
return newItem;
};
// 手动触发全量同步
const triggerFullSync = async () => {
setSyncStatus('正在同步数据...');
setSyncProgress(0);
try {
const result = await SyncService.fullSync('items', (progress) => {
setSyncProgress(progress);
});
if (result.success) {
setSyncStatus(`同步成功: ${result.message}`);
// 刷新UI显示最新数据
loadItemsFromStorage();
} else {
setSyncStatus(`同步失败: ${result.error}`);
}
} catch (error) {
setSyncStatus(`同步出错: ${error.message}`);
} finally {
setTimeout(() => setSyncStatus(''), 3000);
}
};
四、高级应用:离线优先笔记应用架构
4.1 系统架构设计
4.2 核心实现代码
笔记服务实现:
// services/NoteService.js
import { StorageService } from '../storage/AsyncStorageService';
import { FileSystemService } from '../storage/FileSystemService';
import { SyncService } from '../sync/SyncService';
import { v4 as uuidv4 } from 'uuid';
export const NoteService = {
/**
* 生成本地ID
* @returns {string} - 本地唯一ID
*/
generateLocalId() {
return `local_${uuidv4()}`;
},
/**
* 获取所有笔记
* @param {Object} options - 查询选项
* @param {boolean} [options.includePendingSync=false] - 是否包含待同步项
* @returns {Promise<Array<Object>>} - 笔记列表
*/
async getAllNotes(options = {}) {
const notes = await StorageService.getItem('notes_list') || [];
// 过滤掉已删除的笔记
let result = notes.filter(note => !note.isDeleted);
// 如果不包含待同步项,则过滤掉
if (!options.includePendingSync) {
result = result.filter(note => !note.isPendingSync);
}
// 按更新时间降序排序
return result.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
},
/**
* 获取单个笔记
* @param {string} id - 笔记ID
* @returns {Promise<Object|null>} - 笔记对象或null
*/
async getNoteById(id) {
const notes = await StorageService.getItem('notes_list') || [];
const note = notes.find(n => n.id === id);
if (!note || note.isDeleted) return null;
// 如果有富文本内容,从文件系统加载
if (note.hasRichContent) {
try {
note.content = await FileSystemService.readFile(`notes/${note.id}.md`);
} catch (error) {
console.error('读取笔记内容失败:', error);
note.content = note.content || '无法加载笔记内容';
}
}
return note;
},
/**
* 创建新笔记
* @param {Object} noteData - 笔记数据
* @param {string} noteData.title - 标题
* @param {string} noteData.content - 内容
* @param {boolean} [noteData.hasRichContent=false] - 是否为富文本
* @param {Array<string>} [noteData.tags=[]] - 标签
* @returns {Promise<Object>} - 创建的笔记
*/
async createNote(noteData) {
const newNote = {
id: this.generateLocalId(),
title: noteData.title,
content: noteData.content,
tags: noteData.tags || [],
hasRichContent: noteData.hasRichContent || false,
isPendingSync: true,
isDeleted: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
// 获取现有笔记列表
const notes = await StorageService.getItem('notes_list') || [];
notes.push(newNote);
// 保存笔记元数据到AsyncStorage
await StorageService.setItem('notes_list', notes);
// 如果是富文本,保存内容到文件系统
if (newNote.hasRichContent) {
await FileSystemService.writeFile(
`notes/${newNote.id}.md`,
newNote.content
);
// 清空内存中的内容,节省内存
newNote.content = '[富文本内容 - 从文件加载]';
}
// 添加到同步队列
await SyncService.queueOperation({
type: 'CREATE',
entity: 'notes',
data: newNote
});
// 尝试立即同步
await SyncService.processQueue();
return newNote;
},
/**
* 更新笔记
* @param {string} id - 笔记ID
* @param {Object} updates - 更新数据
* @returns {Promise<Object>} - 更新后的笔记
*/
async updateNote(id, updates) {
const notes = await StorageService.getItem('notes_list') || [];
const index = notes.findIndex(n => n.id === id);
if (index === -1) {
throw new Error(`找不到ID为 ${id} 的笔记`);
}
// 合并更新数据
const updatedNote = {
...notes[index],
...updates,
updatedAt: new Date().toISOString(),
isPendingSync: true
};
notes[index] = updatedNote;
// 保存元数据
await StorageService.setItem('notes_list', notes);
// 如果更新了内容且是富文本,更新文件
if (updates.content && updatedNote.hasRichContent) {
await FileSystemService.writeFile(
`notes/${updatedNote.id}.md`,
updates.content
);
// 如果返回更新后的笔记,清空内容字段
updatedNote.content = '[富文本内容 - 从文件加载]';
}
// 添加到同步队列
await SyncService.queueOperation({
type: 'UPDATE',
entity: 'notes',
id: updatedNote.id,
data: updatedNote
});
// 尝试立即同步
await SyncService.processQueue();
return updatedNote;
},
/**
* 删除笔记
* @param {string} id - 笔记ID
* @returns {Promise<boolean>} - 操作结果
*/
async deleteNote(id) {
const notes = await StorageService.getItem('notes_list') || [];
const index = notes.findIndex(n => n.id === id);
if (index === -1) {
throw new Error(`找不到ID为 ${id} 的笔记`);
}
// 软删除:标记为已删除,而不是实际删除
notes[index].isDeleted = true;
notes[index].isPendingSync = true;
notes[index].updatedAt = new Date().toISOString();
await StorageService.setItem('notes_list', notes);
// 添加到同步队列
await SyncService.queueOperation({
type: 'DELETE',
entity: 'notes',
id: id
});
// 尝试立即同步
await SyncService.processQueue();
return true;
}
};
五、性能优化与最佳实践
5.1 存储性能优化策略
-
数据分层存储
- 元数据和小型数据:AsyncStorage
- 大型二进制数据:文件系统
- 敏感数据:加密存储
-
查询优化
// 优化前:每次查询都遍历整个数组 const getNotesByTag = (tag) => { const notes = await StorageService.getItem('notes_list'); return notes.filter(note => note.tags.includes(tag)); }; // 优化后:维护标签索引 const buildTagIndex = async () => { const notes = await StorageService.getItem('notes_list'); const tagIndex = {}; notes.forEach(note => { note.tags.forEach(tag => { if (!tagIndex[tag]) tagIndex[tag] = []; tagIndex[tag].push(note.id); }); }); await StorageService.setItem('tag_index', tagIndex); }; // 使用索引查询 const getNotesByTagOptimized = async (tag) => { const tagIndex = await StorageService.getItem('tag_index') || {}; const noteIds = tagIndex[tag] || []; if (noteIds.length === 0) return []; const notes = await StorageService.getItem('notes_list'); return notes.filter(note => noteIds.includes(note.id) && !note.isDeleted); }; -
批量操作
// 批量保存笔记,减少I/O操作 async function batchSaveNotes(notes) { // 1. 先保存所有富文本内容到文件系统 const filePromises = notes .filter(note => note.hasRichContent && note.content) .map(note => FileSystemService.writeFile( `notes/${note.id}.md`, note.content ) ); // 并行处理文件写入 await Promise.all(filePromises); // 2. 清空内容字段节省存储空间 const notesForStorage = notes.map(note => note.hasRichContent ? { ...note, content: '[富文本内容 - 从文件加载]' } : note ); // 3. 批量保存元数据 await StorageService.setItem('notes_list', notesForStorage); }
5.2 错误处理与恢复机制
// storage/ErrorHandling.js
export const StorageErrorTypes = {
NETWORK_ERROR: 'NETWORK_ERROR',
STORAGE_FULL: 'STORAGE_FULL',
AUTH_ERROR: 'AUTH_ERROR',
CONFLICT_ERROR: 'CONFLICT_ERROR',
FILE_NOT_FOUND: 'FILE_NOT_FOUND',
UNSUPPORTED_OPERATION: 'UNSUPPORTED_OPERATION',
GENERIC_ERROR: 'GENERIC_ERROR'
};
export const ErrorHandler = {
/**
* 分类错误类型
* @param {Error} error - 错误对象
* @returns {Object} - 分类后的错误信息
*/
classifyError(error) {
if (!error) {
return {
type: StorageErrorTypes.GENERIC_ERROR,
message: '未知错误',
originalError: error
};
}
// 根据错误消息分类
if (error.message.includes('网络') || error.message.includes('offline')) {
return {
type: StorageErrorTypes.NETWORK_ERROR,
message: '网络连接错误,请检查网络设置',
originalError: error
};
}
if (error.message.includes('storage') || error.message.includes('full')) {
return {
type: StorageErrorTypes.STORAGE_FULL,
message: '存储空间不足,请清理空间后重试',
originalError: error
};
}
if (error.message.includes('认证') || error.message.includes('401')) {
return {
type: StorageErrorTypes.AUTH_ERROR,
message: '认证失败,请重新登录',
originalError: error
};
}
if (error.message.includes('conflict') || error.message.includes('409')) {
return {
type: StorageErrorTypes.CONFLICT_ERROR,
message: '数据冲突,请解决冲突后重试',
originalError: error
};
}
if (error.message.includes('not found') || error.message.includes('404')) {
return {
type: StorageErrorTypes.FILE_NOT_FOUND,
message: '文件不存在或已被删除',
originalError: error
};
}
return {
type: StorageErrorTypes.GENERIC_ERROR,
message: error.message || '操作失败',
originalError: error
};
},
/**
* 错误恢复策略
* @param {Object} errorInfo - 分类后的错误信息
* @param {Function} retryAction - 重试函数
* @returns {Promise<Object>} - 恢复结果
*/
async handleRecovery(errorInfo, retryAction) {
switch (errorInfo.type) {
case StorageErrorTypes.NETWORK_ERROR:
// 网络错误:等待网络恢复后重试
return new Promise((resolve) => {
const unsubscribe = NetInfo.addEventListener(state => {
if (state.isConnected && state.isInternetReachable) {
unsubscribe();
retryAction().then(resolve).catch(resolve);
}
});
// 设置超时,5分钟后放弃
setTimeout(() => {
unsubscribe();
resolve({
success: false,
error: '网络仍不可用,已取消重试'
});
}, 5 * 60 * 1000);
});
case StorageErrorTypes.STORAGE_FULL:
// 存储满:尝试清理缓存
await this.clearCache();
return retryAction();
case StorageErrorTypes.AUTH_ERROR:
// 认证错误:触发重新登录流程
AuthService.logout();
NavigationService.navigate('Login', { needRelogin: true });
throw errorInfo; // 不重试,需要用户干预
case StorageErrorTypes.CONFLICT_ERROR:
// 冲突错误:调用冲突解决策略
return ConflictResolver.resolve(errorInfo, retryAction);
default:
// 其他错误:简单重试3次
for (let i = 0; i < 3; i++) {
try {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
const result = await retryAction();
return result;
} catch (retryError) {
if (i === 2) throw retryError; // 最后一次失败抛出错误
}
}
}
},
/**
* 清理缓存释放空间
* @returns {Promise<boolean>} - 是否清理成功
*/
async clearCache() {
try {
// 1. 删除30天前的缓存文件
const cacheDir = await FileSystemService.getDocumentDirectory('cache');
const files = await FileSystemService.readDirectory(cacheDir);
const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000;
for (const file of files) {
if (file.mtime < thirtyDaysAgo) {
await FileSystemService.deleteFile(file.path);
}
}
// 2. 清理已删除但保留的笔记文件
const notes = await StorageService.getItem('notes_list') || [];
const validNoteIds = new Set(notes.filter(n => !n.isDeleted).map(n => n.id));
const noteFiles = await FileSystemService.readDirectory('notes');
for (const file of noteFiles) {
const noteId = file.name.replace('.md', '');
if (!validNoteIds.has(noteId)) {
await FileSystemService.deleteFile(file.path);
}
}
return true;
} catch (error) {
console.error('清理缓存失败:', error);
return false;
}
}
};
六、总结与未来趋势
React Native的存储方案正朝着离线优先和无缝同步的方向发展。随着Web标准的普及,我们看到越来越多的Web API被引入React Native生态,如File System Access API和Background Sync API。同时,新兴的存储技术如Watermelon DB提供了更强大的本地数据库能力,结合GraphQL订阅可以实现毫秒级的实时数据同步。
未来的移动应用存储架构将更加注重:
- 边缘计算与本地智能处理
- 端到端加密的全链路安全
- 增量同步与冲突自动解决
- 持久化UI状态与离线首屏渲染
作为开发者,我们需要根据项目规模和需求选择合适的存储方案,同时保持对新兴技术的关注,构建既满足当前需求又具备未来扩展性的存储系统。
通过本文介绍的存储方案和最佳实践,您应该能够构建一个可靠、高效且用户友好的React Native应用数据存储系统,为用户提供流畅的离线体验和无缝的跨设备同步能力。
附录:常用存储库与资源
| 库名称 | 功能描述 | GitHub星数 | 适用场景 |
|---|---|---|---|
| @react-native-async-storage/async-storage | 异步键值存储 | 5.8k+ | 简单数据、用户设置 |
| react-native-fs | 文件系统访问 | 5.9k+ | 大型文件、二进制数据 |
| react-native-keychain | 安全存储 | 4.7k+ | 密码、令牌、敏感信息 |
| react-native-sqlite-storage | SQLite数据库 | 5.3k+ | 复杂查询、关系数据 |
| realm | 移动端数据库 | 12.9k+ | 高性能本地数据库 |
| watermelondb | 高级离线数据库 | 2.7k+ | 复杂离线同步应用 |
| redux-persist | Redux状态持久化 | 12.8k+ | Redux应用状态存储 |
| mobx-persist | MobX状态持久化 | 1.1k+ | MobX应用状态存储 |
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



