You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Expo裸工作流React Native应用的内存泄漏问题?

针对Expo裸工作流RN应用内存泄漏的排查方案

一、先处理Expo AV的资源释放(高优先级)

音频实例是最容易引发内存泄漏的点,必须确保页面卸载时完全释放:

  • 每个Audio.Sound实例都要在组件卸载时调用unloadAsync(),不能仅用pauseAsync()。在useEffect的清理函数中执行:
import { Audio } from 'expo-av';

useEffect(() => {
  let soundInstance;
  const initSound = async () => {
    soundInstance = new Audio.Sound();
    await soundInstance.loadAsync(require('./audio.mp3'));
  };
  initSound();

  return async () => {
    if (soundInstance) {
      await soundInstance.unloadAsync();
    }
  };
}, []);
  • 检查是否存在全局缓存的音频实例(比如放在Redux、Context中),页面卸载后未被清除,导致实例持续占用内存。
  • 避免在组件渲染周期内频繁创建新的音频实例,尽量复用,但复用的实例在不再需要时也要及时释放。

二、验证React Navigation页面的卸载逻辑

  • 确认组件的卸载回调是否触发:在useEffect的清理函数中添加日志,切换页面时查看控制台是否输出,判断页面是否真正被卸载:
useEffect(() => {
  return () => {
    console.log('当前页面已执行卸载清理');
  };
}, []);
  • 检查导航事件订阅是否正确取消:如果使用了navigation.addListener,必须在清理函数中移除订阅,否则会保留对组件的引用:
useEffect(() => {
  const focusListener = navigation.addListener('focus', () => {
    // 聚焦逻辑
  });
  const blurListener = navigation.addListener('blur', () => {
    // 失焦逻辑
  });

  return () => {
    focusListener();
    blurListener();
  };
}, [navigation]);

三、清理React Reanimated 3的动画资源

  • 对于循环动画或手动创建的动画控制器,需要在页面卸载时停止并重置:
import { useSharedValue, withRepeat, withTiming } from 'react-native-reanimated';

const progress = useSharedValue(0);
useEffect(() => {
  progress.value = withRepeat(withTiming(1, { duration: 2000 }), -1);
  
  return () => {
    // 立即停止动画并重置值,避免动画持续占用资源
    progress.value = withTiming(0, { duration: 0 });
  };
}, []);
  • 不要将动画相关的sharedValue或动画对象存储到全局状态或父组件的引用中,防止组件卸载后引用无法被回收。

四、用工具定位泄漏源

  • XCode Memory Graph Debugger:
    1. 运行App后,点击XCode调试栏的「Debug Memory Graph」按钮
    2. 切换几次页面,再次抓取内存快照
    3. 搜索你的组件类名(比如PlayerScreen),查看是否存在多个未被释放的实例,通过引用链找到泄漏的根源(比如某个全局变量、未取消的订阅)
  • Flipper Memory Inspector:
    在Flipper中打开Memory Inspector,对比页面切换前后的JS内存占用,查看哪些对象的数量持续增长,定位未被回收的对象。

五、排查其他潜在泄漏点

  • 检查全局事件监听(如AppState.addEventListener、Keyboard.addListener)是否在页面卸载时移除
  • 清理组件中使用的setInterval/setTimeout,在卸载函数中调用clearInterval/clearTimeout
  • 如果使用了第三方UI组件,查看组件文档是否有需要手动释放资源的API(比如自定义的轮播、动画组件)

内容的提问来源于stack exchange,提问作者Demetrius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:23:26