在项目中,很多场景都会需要考虑切后台切换的场景,于是就会使用AppState这个组件,以下是官网中的事例代码。
constructor(props) {
super(props);
this.state = {
currentAppState: AppState.currentState,
};
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextAppState) => {
if (this.state.currentAppState.match(/inactive|background/) && nextAppState === 'active') {
console.log('App has come to the foreground!')
}
this.setState({currentAppState: nextAppState});
}
render() {
return (
<Text>Current state is: {this.state.currentAppState}</Text>
);
}
但是有个问题,上述写法看似是ES6的语法,但是在ES6中直接绑定this._handleAppStateChange这个方法,在函数体内是无法访问this的,但是实例代码中_handleAppStateChange方法体内直接使用了this,这在ES6下根本无法实现的,要想使用this就需要写成this._handleAppStateChange.bind(this),于是在自己的项目中使用bind方法。
结果在页面销毁后,惊人的发现,前后台切换后还是能够走_handleAppStateChange方法,也就是对象没有被释放掉!!!
后来经Google得知,bind操作会重新生成一个实例,就会导致在addEventListener时绑定的方法和removeEventListener的时候,不是同一个对象,从而导致没有从监听中移除该方法。
解决方案:
this._handleAppStateChangeHandle = this._handleAppStateChange.bind(this);
AppState.addEventListener('change', this._handleAppStateChangeHandle);
AppState.removeEventListener('change', this._handleAppStateChangeHandle) ;
通过一个变量去保存bind生成的实例对象,这样就保证了添加和移除的时候是同一个对象,经测试问题已解决。
网友评论