Reduce iOS memory pressure: lightbox windowing, memory warning handler
- Lightbox pager: only mount ±1 neighbor of the current page so a multi-image post no longer decodes every fullsize image up front. - App: respond to iOS memoryWarning events by clearing expo-image's in-memory cache, giving the GC a stronger hint before jetsam. - GIF picker: priority="low" + recyclingKey on item Image. Minor; the picker's masonry grid still needs proper row virtualization. Hypothesis-driven against APP-D9 breadcrumb patterns; needs TestFlight validation before claiming any rate reduction.
This commit is contained in:
+12
@@ -1,12 +1,14 @@
|
|||||||
import '#/logger/sentry/setup'
|
import '#/logger/sentry/setup'
|
||||||
|
|
||||||
import {Fragment, useEffect, useState} from 'react'
|
import {Fragment, useEffect, useState} from 'react'
|
||||||
|
import {DeviceEventEmitter} from 'react-native'
|
||||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
||||||
import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller'
|
import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller'
|
||||||
import {
|
import {
|
||||||
initialWindowMetrics,
|
initialWindowMetrics,
|
||||||
SafeAreaProvider,
|
SafeAreaProvider,
|
||||||
} from 'react-native-safe-area-context'
|
} from 'react-native-safe-area-context'
|
||||||
|
import {Image} from 'expo-image'
|
||||||
import * as ScreenOrientation from 'expo-screen-orientation'
|
import * as ScreenOrientation from 'expo-screen-orientation'
|
||||||
import * as SplashScreen from 'expo-splash-screen'
|
import * as SplashScreen from 'expo-splash-screen'
|
||||||
import * as SystemUI from 'expo-system-ui'
|
import * as SystemUI from 'expo-system-ui'
|
||||||
@@ -141,6 +143,16 @@ function InnerApp() {
|
|||||||
})
|
})
|
||||||
}, [l])
|
}, [l])
|
||||||
|
|
||||||
|
// Respond to iOS memory warnings before the OS jetsams us. expo-image trims
|
||||||
|
// its own cache on warning, but explicitly clearing it gives the GC a stronger
|
||||||
|
// hint and frees decoded bitmaps no longer in active use.
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = DeviceEventEmitter.addListener('memoryWarning', () => {
|
||||||
|
void Image.clearMemoryCache()
|
||||||
|
})
|
||||||
|
return () => sub.remove()
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alf theme={theme}>
|
<Alf theme={theme}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ function ImageView({
|
|||||||
style={styles.pager}>
|
style={styles.pager}>
|
||||||
{images.map((imageSrc, i) => (
|
{images.map((imageSrc, i) => (
|
||||||
<View key={`${i}-${imageSrc.uri}`}>
|
<View key={`${i}-${imageSrc.uri}`}>
|
||||||
|
{Math.abs(i - imageIndex) <= 1 ? (
|
||||||
<LightboxImage
|
<LightboxImage
|
||||||
onTap={onTap}
|
onTap={onTap}
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
@@ -431,6 +432,7 @@ function ImageView({
|
|||||||
thumbRects={thumbRects}
|
thumbRects={thumbRects}
|
||||||
imageIndex={i}
|
imageIndex={i}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
))}
|
))}
|
||||||
</PagerView>
|
</PagerView>
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export function GifPickerItem({
|
|||||||
accessibilityLabel={gif.title}
|
accessibilityLabel={gif.title}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
cachePolicy="none"
|
cachePolicy="none"
|
||||||
|
priority="low"
|
||||||
|
recyclingKey={gif.id}
|
||||||
accessibilityIgnoresInvertColors
|
accessibilityIgnoresInvertColors
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user