当我滚动 Flatlist 时,内存使用量越来越高,并且当我停止滚动时内存不会释放(React Native)

Lyn*_*ynn 8 memory reactjs react-native react-native-flatlist react-native-sectionlist

我在我的 React Native 项目中使用 Flatlist 和 SectionList,并且有 300 多行数据。然而,我发现一个严重的问题,就是当我不断向下和向上滚动时,内存使用率越来越高。我怎么解决这个问题?或者我怎样才能释放内存?

我知道这里有一些相关的问题,但我尝试了很多解决方案,但没有一个有效。

举些例子,

1.我使用了Pure.component或者shouldcomponentUpdate

2.我使用了Flatlist和SectionList的一些props

initialNumToRender={9}
windowSize={10}
maxToRenderPerBatch={2}
removeClippedSubviews={true}
disableVirtualization={true}
getItemLayout={this.getItemLayout}
keyExtractor={(item, index) => item[0]}
extraData={this.state}
Run Code Online (Sandbox Code Playgroud)

还有其他解决方案可以帮助我解决问题吗?多谢!

小智 5

disableVirtualization={true}基本上关闭了 FlatList 提供的虚拟化功能,所以如果内存是一个问题,我不推荐它。所以我首先要删除这个道具。

然后,我会调查问题是否是项目太多(因此需要太多 RAM 才能将它们保留在 UI 中),或者项目中是否存在内存泄漏(因此即使将它们从用户界面仍然消耗内存)

FlatList 的 windowSize 控制将保留渲染多少“不可见”项目。如果将 windowSize 设置为“1”,则仅渲染可见项目(尝试一下,看看滚动 FlatList 时会发生什么)。windowSize 为“21”(默认值)将渲染可见项目,并在可见区域的左侧和右侧(或顶部和底部)加上 10 个“窗口”。因此,如果窗口尺寸为 1000 像素,则任何当前不可见但距可见区域小于 10000 像素的项目都将由 FlatList 提前渲染。

这就是我解决问题的方法:

  • 首先,我将 windowSize 设置为一个非常大的值(例如 100),以确保所有 300 多行都将保留在内存中。您可以打开应用程序并等待一段时间,直到所有项目都已渲染(如果您有 300 多个项目并且 maxToRenderPerBatch 设置为 2,这意味着 FlatList 将需要 150 多个“周期”来完成渲染所有内容,因此可能需要一段时间.您还可以,仅为了这个实验,将initialNumToRender设置为一个非常高的数字(例如1000),以便当列表渲染时您知道它已经完全渲染。但在这种情况发生之前应用程序可能会冻结几秒钟)。列表全部显示完毕后,查看您的应用程序使用了多少内存。在这种情况下,上下滚动不应增加内存使用量,因为一切都已经在 UI 中了:-)。记下这个内存量,因为它将是您的基线。
  • 其次,我会将 windowSize 设置为尽可能小的数字(例如 1)。现在,当您打开包含大量数据的屏幕时,React 将仅渲染屏幕中可见的内容。内存的使用量应该比前一种情况小很多。然而,当你滚动时,由于 windowSize 受限,React 将不断销毁并创建新的 UI 元素。如果您滚动的次数越多,使用的内存就越多(并且即使您停止滚动一段时间,它也永远不会回去),那么您的视觉组件中可能存在内存泄漏,需要修复。如果这是真的,缓慢地一直滚动到列表底部并缓慢地一直滚动回顶部甚至可能会导致比第一种情况使用更多的 RAM。

内存泄漏可能很难发现,因此我希望只需调整 windowSize 和其他一些设置就能得到您需要的结果。如果存在内存泄漏,这是我最近读过的一篇有趣的文章: https: //blog.swmansion.com/hunting-js-memory-leaks-in-react-native-apps-bd73807d0fde

另外,避免使用调试版本检查 RAM 使用情况:它们不仅使用更多内存,调试工具(如 console.log 等)可能会产生发布版本中实际不存在的泄漏。