react-native中的应用状态不会删除侦听器

时间:2018-05-28 11:33:09

标签: react-native react-native-ios

我已按以下方式添加了侦听器(尝试同时放入构造函数和componentDidMount): AppState.addEventListener('更改',this._handleAppStateChange);

并在componentWillUnmount方法中以下列方式删除了侦听器:

AppState.removeEventListener('更改',this._handleAppStateChange);

在回调函数中:

  _handleAppStateChange = (nextAppState) => {
    setTimeout(() => {
      alert('App state: ' + this.state.appState);
      alert('Next App state: ' + nextAppState);
    }, 0);
  }

它会多次发出警报。 它不会删除一次配置的侦听器。 如果有人知道,请告诉我?

5 个答案:

答案 0 :(得分:1)

根据代码的外观,我假设您正在使用类组件。我最终解决它的方法是创建一个指针函数,该指针函数指向this范围内的实际函数,而无需使用.bind(this)

例如

// Actual Function    
handleAppStateChange(state) {
  // Work your magic!
}

// Pointer
handleAppStateChangeCall = (state) => this.handleAppStateChange(state);

// Setup listener event
setupAppStateListener() {
  AppState.addEventListener("change", this.handleAppStateChangeCall);
}

// Clear listener event
clearAppStateListener() {
  AppState.addEventListener("change", this.handleAppStateChangeCall);
}

// Mounted Hook
componentDidMount() { 
  setupAppStateListener();
}

// Unmount Hook
componentWillUnmount() {
  clearAppStateListener()
}

答案 1 :(得分:0)

您必须从ComponentWillUnmount功能

中删除侦听器
componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

答案 2 :(得分:0)

设置状态是异步过程。因此,在componentWillUnmount中不要将它用作组件获取卸载,并且仍然对于该场景,setState正在进行中,从而导致警报。

答案 3 :(得分:0)

可能是由于您正在监听的功能发生改变

this.props.navigation.addListener(
  'didFocus',
  () => {
    AppState.addEventListener('change', this.handleAppStateChange)
  }
)
this.props.navigation.addListener(
  'willBlur',
  () => {
    AppState.removeEventListener('change', this.handleAppStateChange)
  }
)

正常工作

this.props.navigation.addListener(
  'didFocus',
  () => {
    AppState.addEventListener('change', this.handleAppStateChange.bind(this))
  }
)
this.props.navigation.addListener(
  'willBlur',
  () => {
    AppState.removeEventListener('change', this.handleAppStateChange.bind(this))
  }
)

不起作用 所以也许你需要这样

this.handleAppStateChange = this.handleAppStateChange.bind(this)

在您的构造函数中

答案 4 :(得分:0)

最近几天遇到了同样的问题。 我终于通过将应用程序状态管理迁移到App.js组件并创建了服务管理器来对其进行管理。

下面是我的App.js的样子:

import {AppState } from "react-native";
import {AppStateService} from "YOUR_PATH_TO_THE_NEXT_FILE";

export default function App() {

    // Listen to app state
    AppStateService.init();
    useEffect(() => {
        AppState.addEventListener('change', AppStateService.getInstance().handleAppStateChange);
        return (() => {
            AppState.removeEventListener('change', AppStateService.getInstance().handleAppStateChange);
        })
    }, []);

    return (/*Rendering stuff (navigation, error boundary, ...*/);
}

AppStateService.js

/**
 * Class to allow us to refer to the app state service
 */

export class AppStateService {

    static instance;

    static STATE_ACTIVE         = 'active';
    static STATE_INACTIVE       = 'inactive';
    static STATE_BACKGROUND     = 'background';
    static STATE_NOT_LAUNCHED   = 'not_launched';

    previousState   = AppStateService.STATE_NOT_LAUNCHED;
    currentState    = AppStateService.STATE_ACTIVE;

    handlers = {};

    appLaunchId = 0;

    /**
     * @returns {AppStateService}
     */
    static getInstance() {
        if(!this.instance){
            this.instance = new AppStateService();
        }

        return this.instance;
    }

    static init = () => {
        // This func need to be call in the App.js, it's just here to create the instance
        const instance = AppStateService.getInstance();

        instance.appLaunchId = new Date().getTime() / 1000;
    }

    handleAppStateChange = (nextState) => {
        if(nextState !== this.currentState) {
            this.previousState = this.currentState;
            this.currentState = nextState;

            for (const [key, handler] of Object.entries(this.handlers)) {
                handler(nextState);
            }
        }
    }

    getCurrentState = () => {
        return this.currentState;
    }

    getPreviousState = () => {
        return this.previousState;
    }

    addStateHandler = (key, handler) => {
        this.handlers[key] = handler;
    }

    hasStateHandler = (key) => {
        if( this.handlers[key] ){
            return true;
        }

        return false;
    }

    removeStateHandler = (key) => {
        delete this.handlers[key];
    }
}

现在这里是如何在应用程序组件中的任何位置调用它的方法:

export default class RandomComponent extends React.Component {
    
    componentDidMount() {
        // Check app going background or not
        this.handleAppStateChange = this.handleAppStateChange.bind(this);
        AppStateService.getInstance().addStateHandler('myListenerCustomKey', this.handleAppStateChange);
    }

    componentWillUnmount() {
        // Remove app state change listener
        AppStateService.getInstance().removeStateHandler('myListenerCustomKey');
    }

    handleAppStateChange = (nextAppState) => {
        console.log("I'm going to be -" + nextAppState + "- while I was -" + AppStateService.getInstance().getPreviousState() + "-");
    }
}

通过这种方式,您可以在应用程序中的任何位置侦听应用程序的前台/非活动/后台状态,并正确订阅/取消订阅这些事件。

相关问题