簡體   English   中英

Memory React Native Android App 使用 setTimeout 泄漏

[英]Memory Leak in React Native Android App using setTimeout

我有一個 React Native Android 電視應用程序,用於在電視上顯示數字標牌內容。 在應用程序運行大約一個小時后,我收到了幾個 outOfMemory 異常。 我的應用程序最初呈現一個使用setTimeout每 1 秒運行一次的Player組件。 每一秒,該組件都會遍歷一個 JSON 數組,該數組包含有關不同圖像或視頻的信息。 根據幾個條件, Player組件將更新currentAsset值 currentAsset 並重新渲染Asset組件,顯示視頻或圖像指定的秒數。 為了重現currentAsset異常,我使 currentAsset 的值每 1 秒從自動播放視頻到圖像來回切換,因此它實際上在屏幕上顯示圖像一秒鍾,然后是視頻並無限重復。 雖然這不是典型用法,但它是我能夠重新創建 memory 異常的最快方法。

這是我的骨架代碼:

class Player extends Component {
    constructor(props) {
      super(props)
      this.currentAsset = null
      this.state = { currentAsset: null }
    }

    componentDidMount(){
        //create cache directory initializes file caching for the player
        createCacheDirectory().then(() => {
            this.play()
        })
    }

    poll = () => {
        //conditional here to either poll an API for updates and call play or just call play

        if(canCallAPI){
          //this condition happens every 30 seconds
          //might call setState in a promise which also saves files locally to the device. 
          callAPI().then(() => {
               //some other setup stuff here
               play();
          })
        }

        play()
    }

    play = () => {

        //there is more logic here but the idea is that I get a new object containing a file/video path which I pass to the `Asset` Component
        this.currentAsset = this.getCurrentAssetFromJSONArray();
    
        this.setState({ currentAsset: this.currentAsset });
        this.timeout = setTimeout(this.poll, 1000);
    }
 
    render() {
        return (<Asset asset={this.state.currentAsset} />);
    }
end

Asset組件非常簡單,只檢查this.state.currentAsset.file_type的值並根據當前文件類型呈現<Image /><Video />

有一個 memory 泄漏,因為每次組件重新渲染它都會創建一個新的計時器實例而不清除以前的實例。

我們需要在組件卸載時清除計時器。

class Player extends Component {
  constructor(props) {
    super(props);
    this.currentAsset = null;
    this.state = { currentAsset: null };
    this.timeout = null;
  }

  componentDidMount() {
    //create cache directory initializes file caching for the player
    createCacheDirectory().then(() => {
      this.play();
    });
  }

  poll = () => {
    //conditional here to either poll an API for updates and call play or just call play

    if (canCallAPI) {
      //this condition happens every 30 seconds
      //might call setState in a promise which also saves files locally to the device.
      callAPI().then(() => {
        //some other setup stuff here
        play();
      });
    }

    play();
  };

  play = () => {
    //there is more logic here but the idea is that I get a new object containing a file/video path which I pass to the `Asset` Component
    this.currentAsset = this.getCurrentAssetFromJSONArray();

    this.setState({ currentAsset: this.currentAsset });
    this.timeout = setTimeout(this.poll, 1000);
  };

  componentWillUnmount() {
    // Clear current timeout when component unmount
    if (this.timeout) {
      clearTimeout(this.timer);
    }
  }

  render() {
    return <Asset asset={this.state.currentAsset} />;
  }
}


暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM