facebook/react-native

Memory leak when programmatically changing 'source' prop of Image

開放

#12,220 建立於 2017年2月5日

 (21 則留言) (17 個反應) (0 位負責人)C++ (25,149 個分叉)batch import
BugComponent: ImageGood first issuePlatform: iOS

倉庫指標

星標
 (125,808 顆星)
PR 合併指標
 (PR 指標待抓取)

描述

Description

If you use an Image component in render and use the parent component's state to manage the source prop, each time the source is changed the previous source is not deallocated. Even when the parent component is unmounted, the previous images still use memory.

Reproduction

I've made a simple ImageTest project that demonstrates the bug. (IMPORTANT: run app in release mode to experience the issue)

Code:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  TouchableHighlight,
  Dimensions,
} from 'react-native';

import image0 from './images/0.png'
import image1 from './images/1.png'
import image2 from './images/2.png'
import image3 from './images/3.png'
import image4 from './images/4.png'

const images = [
  image0,
  image1,
  image2,
  image3,
  image4,
]

export default class ImageTest extends Component {
  constructor() {
    super()

    this.state = ({
      counter: 0,
    })
  }

  increment = () => {
    this.setState({
      counter: this.state.counter + 1
    })
  }

  render() {
    const imageSource = images[this.state.counter]

    return (
      <View>
        <Image
          source={imageSource}
          style={styles.image}
        />
        <TouchableHighlight onPress={this.increment} style={styles.highlight}>
          <Text style={styles.text}>NEXT IMAGE</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const window = Dimensions.get('window')

const styles = StyleSheet.create({
  highlight: {
    backgroundColor: 'yellow',
    position: 'absolute',
    bottom: 0,
    left: 0,
  },
  text: {
    fontSize: 50,
  },
  image: {
    width: window.width,
    height: window.height,
  },
});

AppRegistry.registerComponent('ImageTest', () => ImageTest);

Solution

Presumably when the source is changed the underlying UIImage/UIImageView needs to be destroyed.

Additional Information

  • React Native version: 0.41.0
  • Platform: iOS
  • Operating System: MacOS 10.12.3 / xcode 8.2

貢獻者指南