ListView leaks memory and doesn't clean up (Android)
See original GitHub issueHi there, I’m using RN 0.41.2 on an Android device (not emulator). I’ve created a really simple ListView component. As I scroll down this list, the memory used by the app increases linearly. If I background the app, this memory doesn’t get cleaned up at all.
While the code below is simple, you can imagine how out-of-hand this gets on a ListView that renders more-detailed rows (including Image and TouchableOpacity). The problem is that the app I’m building is a music streaming app. If I scroll through ~3 pages of tracks, it bring the app’s total consumption up to ~150MB of ram (from an initial boot of 90MB), which makes it the #1 candidate for Android to garbage collect if another app takes the foreground and requires more memory (eg, you want to browse Chrome while listening to the music app in the background). Without the ListView, my app uses up ~55MB – a number similar to the one generated by the simple component below.
I’ve tried this with the new/experimental FlatList component, and I get similar - if not worse - results as far as memory consumption. This is the main thing holding me back from rolling out my React Native version to production (on an app with 500,000+ installs).
import React, { Component } from 'react';
import {
AppRegistry,
Text,
ListView
} from 'react-native';
var data = []
for (var ii = 0; ii < 1000; ii++) {
data.push('row - ' + ii)
}
export default class AwesomeProject extends Component {
constructor() {
super();
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows(data),
};
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
initialListSize={50}
pageSize={50}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
);
}
}
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
Screenshots below created using “adb shell dumpsys meminfo -a com.awesomeproject”
Issue Analytics
- State:
- Created 7 years ago
- Comments:30 (14 by maintainers)
Yeah, 400MB is still a little high - what device are you running on? The heap and cache sizes will vary depending on the device memory. The view count is much more reasonable, but also a bit high. You can try dialing down the
windowSize
too. The default is 21 which is actually quite large.But note that the live memory number is going to be much higher than the background number. That 359mb includes GPU texture buffers and other caches that should be cleared when the app is backgrounded. It also might take a while for the JS Garbage collector to trigger a cleanup and release the memory back to the operating system.
Memory is a very complex issue. Have you tried doing similar analysis with other apps? What happens if you scroll through the same amount of content in the other apps, like Twitter?
Hello! What you are describing here is (sadly) the intended behavior of react-native’s
ListView
component on iOS and Android – it does not recycle views or unmount anything that goes out of view, with the exception of images if you useremoveClippedSubviews
. I see you looked into FlatList @jasongrishkoff – that should help with this problem because it uses windowing – only the contents you can currently see and some buffer around the contents are actually rendered.