refactor: 组件失焦清理图片缓存,解决页面长时间不动OOM

This commit is contained in:
康猛 2026-01-19 17:03:06 +08:00
parent ef4114f694
commit f4ef24b28f
8 changed files with 2833 additions and 42 deletions

View File

@ -1,31 +1,6 @@
# Exclude other apps directories
../apps/*
!../apps/expo-duooomi-app
# Exclude unused packages from the monorepo
../packages/eslint-config/*
../packages/flowgraph/*
../packages/flowgraph-core/*
/android/
/ios/
/dist/
# Exclude root level files that aren't needed for this app
../.agent/
../.gitea/
../.vscode/
../BETTER_AUTH_体系交接文档.md
../CLAUDE.md
../FLOWGRAPH_交接文档.md
../FLOWGRAPH_思维导图.md
../STRIPE_CREDIT_BURNDOWN_交接文档.md
../ai-codegen-guideline.md
../debug-credit-burndown.js
../README.md
# Exclude development and configuration files
../.gitignore
../.prettierignore
../.prettierrc
# Only include necessary package management files
!../pnpm-workspace.yaml
!../package.json
!../pnpm-lock.yaml

View File

@ -115,7 +115,7 @@ const VideoBox = ({ url, needWeb = true, width = 256, style, autoplay = true, ..
}
return (
<Image
cachePolicy="memory-disk"
cachePolicy="disk"
source={{ uri: url }}
style={style as any}
transition={{ duration: 200, effect: 'cross-dissolve' }}

View File

@ -10,7 +10,7 @@ export const IOS_UNIVERSAL_LINK = 'duooomi.bowong.cn'
// 原生版本,原生代码变更时需要更新此版本号
export const VERSION = '1.1.0'
// JavaScript版本JS代码变更时需要更新此版本号
export const APP_VERSION = 'dev202601161658'
export const APP_VERSION = 'dev202601191538'
const ALIPAY_SCHEMA = 'alipay2021006119657394'
const ALIPAY_SCHEMA_SANDBOX = 'alipay9021000158673972'

View File

@ -2,6 +2,7 @@ import { Ionicons } from '@expo/vector-icons'
import { useIsFocused } from '@react-navigation/native'
import { Block, ConfirmModal, Img, ListEmpty, Text, Toast, VideoBox } from '@share/components'
import { FlashList } from '@shopify/flash-list'
import { Image } from 'expo-image'
import { LinearGradient } from 'expo-linear-gradient'
import { router, useFocusEffect } from 'expo-router'
import { observer } from 'mobx-react-lite'
@ -247,6 +248,15 @@ const Index = observer(function Index() {
}
}, [isAuthenticated, user?.id])
// 页面失焦时清理内存缓存,减少内存占用
useEffect(() => {
if (!isFocused) {
// 清理内存缓存,保留磁盘缓存
Image.clearMemoryCache()
// console.log('页面失焦,清理内存缓存')
}
}, [isFocused])
useEffect(() => {
return () => {
userBalanceStore.stopPolling()
@ -359,7 +369,7 @@ const Index = observer(function Index() {
const visibleIdsRef = useRef<Set<string>>(new Set())
const [visibilityVersion, setVisibilityVersion] = useState(0)
// 可见性变化回调 - 简化版
// 可见性变化回调 - 优化版:减少状态更新频率
const onViewableItemsChanged = useCallback(
(info: { viewableItems: { isViewable: boolean; key: string; index: number | null }[] }) => {
const { viewableItems } = info
@ -368,23 +378,31 @@ const Index = observer(function Index() {
// 快速滑动时可能为空,保留上次状态
if (currentVisible.size === 0 && visibleIdsRef.current.size > 0) return
// 添加前后缓冲减少到3个以降低内存占用)
// 添加前后缓冲减少到3个item以降低内存占用)
if (viewableItems.length > 0 && allItems.length > 0) {
const first = viewableItems[0]?.index ?? 0
const last = viewableItems[viewableItems.length - 1]?.index ?? first
if (first !== null && last !== null) {
for (let i = Math.max(0, first - 6); i < first; i++) {
// 每列3个所以前后各加3行9个item
for (let i = Math.max(0, first - 9); i < first; i++) {
if (allItems[i]) currentVisible.add(allItems[i].id)
}
for (let i = last + 1; i < Math.min(allItems.length, last + 7); i++) {
for (let i = last + 1; i < Math.min(allItems.length, last + 10); i++) {
currentVisible.add(allItems[i].id)
}
}
}
// 只有可见项发生显著变化时才更新状态(避免频繁重渲染)
const hasSignificantChange =
Math.abs(currentVisible.size - visibleIdsRef.current.size) > 3 ||
[...currentVisible].some((id) => !visibleIdsRef.current.has(id))
if (hasSignificantChange) {
visibleIdsRef.current = currentVisible
setVisibilityVersion((v) => v + 1)
}
},
[allItems],
)
@ -429,9 +447,11 @@ const Index = observer(function Index() {
}
numColumns={3}
onEndReached={handleLoadMore}
maxItemsInRecyclePool={0}
// 设置合理的回收池大小,避免内存无限增长
maxItemsInRecyclePool={12}
removeClippedSubviews={true}
drawDistance={300}
// 减小预渲染距离,降低内存占用
drawDistance={150}
onEndReachedThreshold={0.3}
refreshControl={<RefreshControl colors={['#FFE500']} refreshing={refreshing} onRefresh={handleRefresh} />}
renderItem={renderItem}

2793
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
"production": {
"channel": "production",
"distribution": "internal",
"bun": "1.3.3",
"bun": "1.3.5",
"ios": {
"image": "latest"
},
@ -32,7 +32,7 @@
"channel": "development",
"developmentClient": true,
"distribution": "internal",
"bun": "1.3.3",
"bun": "1.3.5",
"ios": {
"image": "latest"
},
@ -53,7 +53,7 @@
"test": {
"channel": "test",
"distribution": "internal",
"bun": "1.3.3",
"bun": "1.3.5",
"ios": {
"image": "latest"
},

View File

@ -77,7 +77,7 @@ export const useUpdateChecker = ({
}, [])
// 使用 useInterval 进行定时检查
const updateTimer = setInterval(checkForUpdates, enablePeriodicCheck ? interval : undefined)
// const updateTimer = setInterval(checkForUpdates, enablePeriodicCheck ? interval : undefined)
return {
hasUpdate,

View File

@ -4,6 +4,9 @@
"version": "1.0.0",
"packageManager": "bun@1.3.5",
"private": true,
"bun": {
"install": {}
},
"scripts": {
"postinstall": "patch-package",
"claude": "claude --dangerously-skip-permissions",