refactor(storage): 迁移 AsyncStorage 至 expo-sqlite/kv-store
- 统一替换所有 @react-native-async-storage/async-storage 导入为自定义 kvStore - 新增 kvStore.ts 封装 expo-sqlite/kv-store,保持与 AsyncStorage 完全兼容 - 新增同步读写方法,提升性能 - 引入 expo-sqlite 依赖并更新 lock 文件 BREAKING CHANGE: 移除 @react-native-async-storage/async-storage 依赖,需重新安装依赖并清理旧数据
This commit is contained in:
@@ -6,7 +6,7 @@ import { useCosUpload } from '@/hooks/useCosUpload';
|
||||
import { fetchMyProfile, updateUserProfile } from '@/store/userSlice';
|
||||
import { fetchMaximumHeartRate } from '@/utils/health';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import DateTimePicker from '@react-native-community/datetimepicker';
|
||||
import { Picker } from '@react-native-picker/picker';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import { useRouter } from 'expo-router';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { usePathname, useRouter } from 'expo-router';
|
||||
import { useCallback } from 'react';
|
||||
import { Alert } from 'react-native';
|
||||
|
||||
@@ -112,6 +112,8 @@ PODS:
|
||||
- ExpoModulesCore
|
||||
- ExpoSplashScreen (31.0.8):
|
||||
- ExpoModulesCore
|
||||
- ExpoSQLite (16.0.8):
|
||||
- ExpoModulesCore
|
||||
- ExpoSymbols (1.0.6):
|
||||
- ExpoModulesCore
|
||||
- ExpoSystemUI (6.0.7):
|
||||
@@ -3065,6 +3067,7 @@ DEPENDENCIES:
|
||||
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
|
||||
- ExpoQuickActions (from `../node_modules/expo-quick-actions/ios`)
|
||||
- ExpoSplashScreen (from `../node_modules/expo-splash-screen/ios`)
|
||||
- ExpoSQLite (from `../node_modules/expo-sqlite/ios`)
|
||||
- ExpoSymbols (from `../node_modules/expo-symbols/ios`)
|
||||
- ExpoSystemUI (from `../node_modules/expo-system-ui/ios`)
|
||||
- "ExpoUI (from `../node_modules/@expo/ui/ios`)"
|
||||
@@ -3228,6 +3231,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/expo-quick-actions/ios"
|
||||
ExpoSplashScreen:
|
||||
:path: "../node_modules/expo-splash-screen/ios"
|
||||
ExpoSQLite:
|
||||
:path: "../node_modules/expo-sqlite/ios"
|
||||
ExpoSymbols:
|
||||
:path: "../node_modules/expo-symbols/ios"
|
||||
ExpoSystemUI:
|
||||
@@ -3442,6 +3447,7 @@ SPEC CHECKSUMS:
|
||||
ExpoModulesCore: 5d150c790fb491ab10fe431fb794014af841258f
|
||||
ExpoQuickActions: fdbda7f5874aed3dd2b1d891ec00ab3300dc7541
|
||||
ExpoSplashScreen: 1665809071bd907c6fdbfd9c09583ee4d51b41d4
|
||||
ExpoSQLite: 7fa091ba5562474093fef09be644161a65e11b3f
|
||||
ExpoSymbols: 3efee6865b1955fe3805ca88b36e8674ce6970dd
|
||||
ExpoSystemUI: 6cd74248a2282adf6dec488a75fa532d69dee314
|
||||
ExpoUI: 0f109b0549d1ae2fd955d3b8733b290c5cdeec7e
|
||||
|
||||
21
package-lock.json
generated
21
package-lock.json
generated
@@ -40,6 +40,7 @@
|
||||
"expo-quick-actions": "^5.0.0",
|
||||
"expo-router": "~6.0.4",
|
||||
"expo-splash-screen": "~31.0.8",
|
||||
"expo-sqlite": "^16.0.8",
|
||||
"expo-status-bar": "~3.0.7",
|
||||
"expo-symbols": "~1.0.6",
|
||||
"expo-system-ui": "~6.0.7",
|
||||
@@ -5578,6 +5579,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/await-lock": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://mirrors.tencent.com/npm/await-lock/-/await-lock-2.2.2.tgz",
|
||||
"integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
||||
@@ -8139,6 +8146,20 @@
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-sqlite": {
|
||||
"version": "16.0.8",
|
||||
"resolved": "https://mirrors.tencent.com/npm/expo-sqlite/-/expo-sqlite-16.0.8.tgz",
|
||||
"integrity": "sha512-xw776gFgH4ZM5oGs0spSLNmkHO/kJ/EuRXGzE4/22yII9EmG84vm7aM/M2aEb8taBTqwhSGYUpkwkRT5YFFmsg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"await-lock": "^2.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-status-bar": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-3.0.7.tgz",
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
"expo-quick-actions": "^5.0.0",
|
||||
"expo-router": "~6.0.4",
|
||||
"expo-splash-screen": "~31.0.8",
|
||||
"expo-sqlite": "^16.0.8",
|
||||
"expo-status-bar": "~3.0.7",
|
||||
"expo-symbols": "~1.0.6",
|
||||
"expo-system-ui": "~6.0.7",
|
||||
@@ -81,4 +82,4 @@
|
||||
"typescript": "~5.9.2"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
|
||||
export type AiCoachChatMessage = {
|
||||
id: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { buildApiUrl } from '@/constants/Api';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
|
||||
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { store } from '@/store';
|
||||
import { log } from '@/utils/logger';
|
||||
import { StandReminderHelpers, WaterNotificationHelpers } from '@/utils/notificationHelpers';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import * as BackgroundTask from 'expo-background-task';
|
||||
import * as TaskManager from 'expo-task-manager';
|
||||
import { TaskManagerTaskBody } from 'expo-task-manager';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { buildDefaultCustomFromPlan, DayPlan, ExerciseCustomConfig, generatePilates30DayPlan, PilatesLevel } from '@/utils/pilatesPlan';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
export type DayStatus = 'locked' | 'available' | 'completed';
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
type ExerciseConfigResponse,
|
||||
type ExerciseLibraryItem,
|
||||
} from '@/services/exercises';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
export interface ExerciseLibraryState {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CreateTrainingPlanDto, PlanGoal, PlanMode, TrainingPlan, trainingPlanApi } from '@/services/trainingPlanApi';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { api, setAuthToken, STORAGE_KEYS } from '@/services/api';
|
||||
import { updateUser, UpdateUserDto } from '@/services/users';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { createAsyncThunk, createSelector, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { STORAGE_KEYS } from '@/services/api';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { resetAllGuides } from './guideHelpers';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
|
||||
// 引导状态存储键
|
||||
const GUIDE_KEYS = {
|
||||
|
||||
23
utils/kvStore.ts
Normal file
23
utils/kvStore.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// 直接使用 expo-sqlite/kv-store 作为 AsyncStorage 的替代品
|
||||
// 这是 expo-sqlite 提供的现成 key-value store 实现,完全兼容 AsyncStorage API
|
||||
import Storage from 'expo-sqlite/kv-store';
|
||||
|
||||
// 重新导出所有方法,保持与原 AsyncStorage 相同的接口
|
||||
export const getItem = Storage.getItem.bind(Storage);
|
||||
export const setItem = Storage.setItem.bind(Storage);
|
||||
export const removeItem = Storage.removeItem.bind(Storage);
|
||||
export const getAllKeys = Storage.getAllKeys.bind(Storage);
|
||||
export const multiGet = Storage.multiGet.bind(Storage);
|
||||
export const multiSet = Storage.multiSet.bind(Storage);
|
||||
export const multiRemove = Storage.multiRemove.bind(Storage);
|
||||
export const clear = Storage.clear.bind(Storage);
|
||||
|
||||
// 同步方法(expo-sqlite/kv-store 的特色功能)
|
||||
export const getItemSync = Storage.getItemSync.bind(Storage);
|
||||
export const setItemSync = Storage.setItemSync.bind(Storage);
|
||||
export const removeItemSync = Storage.removeItemSync.bind(Storage);
|
||||
export const getAllKeysSync = Storage.getAllKeysSync.bind(Storage);
|
||||
export const clearSync = Storage.clearSync.bind(Storage);
|
||||
|
||||
// 默认导出,与 AsyncStorage 接口完全兼容
|
||||
export default Storage;
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
|
||||
interface LogEntry {
|
||||
id: string;
|
||||
|
||||
@@ -670,7 +670,7 @@ export class WaterNotificationHelpers {
|
||||
|
||||
// 检查是否在过去2小时内已经发送过喝水提醒,避免重复打扰
|
||||
const lastNotificationKey = '@last_water_notification';
|
||||
const AsyncStorage = (await import('@react-native-async-storage/async-storage')).default;
|
||||
const AsyncStorage = (await import('@/utils/kvStore')).default;
|
||||
const lastNotificationTime = await AsyncStorage.getItem(lastNotificationKey);
|
||||
const now = new Date().getTime();
|
||||
const twoHoursAgo = now - (2 * 60 * 60 * 1000); // 2小时前
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
|
||||
// 用户偏好设置的存储键
|
||||
const PREFERENCES_KEYS = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
// Widget数据同步服务
|
||||
|
||||
Reference in New Issue
Block a user