如何清除应用程序处于后台状态反应本机的间隔?

How to clear interval when app in background state react-native?

我有一个组件每 30 秒获取一个请求,它按预期工作正常。但我希望当应用程序进入后台状态时,请求将停止,而当应用程序处于前台状态时,请求将启动,反之亦然。是否有任何解决方案可以做到这一点。

这是我的组件文件。

Notifications.js

/**
 * Notification Button
 */
import React from "react";
import { View, TouchableWithoutFeedback, Text } from "react-native";
import { connect } from "react-redux";
import Icon from 'react-native-vector-icons/MaterialIcons';
// styles
import styles from "./Styles";
// global styles
import globalStyles from "BkProvider/src/styles/global";
import { colors } from "BkProvider/src/styles/base";
// root navigator
import { rootNavigator } from "BkProvider/src/screens/DashboardGroup";
// strings
import strings from "BkProvider/src/strings";
// actions
import { getSystemAlerts, seeAllSystemAlertLogs, stopNotificationTick } from "BkProvider/src/actions";
// Navigation constants
import NavigationConstants from "BkProvider/src/constants/NavigationConstants";

const { posRelative } = globalStyles;

class NotificationButton extends React.Component {

    componentDidMount() {
        this.props.getSystemAlerts();
    }

    componentWillUnmount() {
        stopNotificationTick();
    }

    /**
     * Function to open system alerts popup
     */
    openSystemAlerts() {
        this.props.seeAllSystemAlertLogs(this.props.unseenAlertLogIdsArray);
        rootNavigator.push({
            screen: NavigationConstants.SYSTEM_ALERTS_LISTING,
            title: strings.allNotifications,
            backButtonTitle: ''
        });
    }

    render() {
        const { unseenAlertLogIdsArray } = this.props;
        return (
            <TouchableWithoutFeedback onPress={this.openSystemAlerts.bind(this)}>
                <View style={styles.button}>
                    <View style={[posRelative]}>
                        <Icon
                            name="notifications-none"
                            size={27}
                            color={colors.white}
                        />
                        {(unseenAlertLogIdsArray && unseenAlertLogIdsArray.length > 0) &&
                            <Text style={styles.badge}>{unseenAlertLogIdsArray.length}</Text>
                        }
                    </View>
                </View>
            </TouchableWithoutFeedback>
        );
    }
}

const mapStateToProps = ({ systemAlerts }) => {
    const { unseenAlertLogIdsArray } = systemAlerts;
    return { unseenAlertLogIdsArray }
}

export default connect(mapStateToProps, {
    getSystemAlerts,
    seeAllSystemAlertLogs
})(NotificationButton);

Actions.js

/**
 * System Alerts Actions
 */
import Toast from "react-native-simple-toast";
import { NetInfo } from "react-native";
// action types
import {
    GET_SYSTEM_ALERTS,
    SEE_ALL_SYSTEM_ALERT_LOGS
} from "BkProvider/src/actions/actionTypes";
// helpers methods
import { getUserId } from "./AppInitializer";
// webservice config
import WebServiceConfig, { APITypes } from "../webservice/WebServiceConfig";
import WebService from "../webservice/WebService";
import APINames from "../webservice/APINames";

let timer = null;
let globalDispatch;
let webServiceObject

/**
 * Function To Get System Alerts
 */
export const getSystemAlerts = () => (dispatch) => {
    clearInterval(timer);
    globalDispatch = dispatch;
    let apiConfig = new WebServiceConfig(APINames.LoadSystemAlertLogs),
        httpParams = {
            'page': "",
            'limit': "",
            'role': 'provider',
            'uid': getUserId()
        }

    webServiceObject = new WebService(onResultCallback)
        .addPostParameterObject(httpParams)
        .addServiceConfiguration(apiConfig)

    timer = setInterval(() => notificationsTick(), 15000);
    notificationsTick();
}

/**
 * API Response Callback Handler
 */
const onResultCallback = (webServiceResultObj) => {
    if (webServiceResultObj.isSuccess && webServiceResultObj.response != null) {
        if (webServiceResultObj.response.api_status === 1) {
            if (globalDispatch) {
                globalDispatch({ type: GET_SYSTEM_ALERTS, payload: webServiceResultObj.response.data });
            }
        }
    } else {
        if (webServiceResultObj.shouldShowErrorMessage)
            Toast.show(webServiceResultObj.errorMessage)
    }
}

/**
 * System Alerts Notification Ticks
 */
const notificationsTick = () => {
    NetInfo.isConnected.fetch().then(isConnected => {
        if (isConnected) {
            if (webServiceObject)
                webServiceObject.execute();
        }
    })
}

/**
 * Function To Clear The Interval Of System Alerts Api
 */
export const stopNotificationTick = () => {
    clearInterval(timer);
}

/**
 * Function To See All System Alerts Logs
 */
export const seeAllSystemAlertLogs = (unseenAlertLogIdsArray) => (dispatch) => {
    if (unseenAlertLogIdsArray) {
        let apiConfig = new WebServiceConfig(APINames.SeeAllSystemAlertLogs)
            .setAPIType(APITypes.POST);

        // params
        let params = {
            role: "provider",
            uid: getUserId(),
            unseen_log_ids: unseenAlertLogIdsArray
        }

        dispatch({ type: SEE_ALL_SYSTEM_ALERT_LOGS }); // dispatch an action to see all system alert logs

        new WebService()
            .addPostParameterObject(JSON.stringify(params))
            .addServiceConfiguration(apiConfig)
            .execute()

    }
}

你应该在这种情况下使用 App state 这是我使用的示例代码

import React, {Component} from 'react'
import {AppState, Text} from 'react-native'

class AppStateExample extends Component {

  state = {
    appState: AppState.currentState
  }

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
  }

  componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

  _handleAppStateChange = (nextAppState) => {
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
      console.log('App has come to the foreground!')
    }
    this.setState({appState: nextAppState});
  }

  render() {
    return (
      <Text>Current state is: {this.state.appState}</Text>
    );
  }

}

有一个 React native API。 https://facebook.github.io/react-native/docs/appstate

这会让您检查应用程序是在后台还是在前台,然后您可以取消请求或继续。

他们文档中的基本用法示例:

import React, {Component} from 'react'
import {AppState, Text} from 'react-native'

class AppStateExample extends Component {

  state = {
    appState: AppState.currentState
  }

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);
  }

  componentWillUnmount() {
    AppState.removeEventListener('change', this._handleAppStateChange);
  }

  _handleAppStateChange = (nextAppState) => {
    if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
      console.log('App has come to the foreground!')
    }
    this.setState({appState: nextAppState});
  }

  render() {
    return (
      <Text>Current state is: {this.state.appState}</Text>
    );
  }

}

此控制台记录应用程序的当前状态,因此您需要将此 AppState 添加到您的状态并执行任何您需要的操作。

调用 notificationsTick 时只需检查 AppState。

if(AppState.currentState === "active"){
    notificationsTick(); 
}

请注意,当您的应用程序处于后台时,JS 计时器可能不会被调用 - 根据我自己的经验,在 iOS 上,单击主页按钮,触摸电源按钮进入睡眠模式,应用程序 Javascript 在 10 秒内被冻结。当您的应用程序返回前台时,它们可能会被调用...您应该测试一下

一个更健壮的实现会保持对计时器的引用,并在应用程序进入后台时取消它。