Как очистить интервал, когда приложение в фоновом режиме реагирует на родной? - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть компонент, который получает запрос каждые 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()

    }
}

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Для этого есть собственный React 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>
    );
  }

}

Эта консоль записывает текущее состояние приложения, поэтому вам нужно добавить это состояние приложения в ваше состояние и делать все, что вам нужно.

0 голосов
/ 14 ноября 2018

Просто проверьте AppState при вызове notificationsTick.

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

Обратите внимание, что таймеры JS могут не вызываться, когда ваше приложение находится в фоновом режиме. Из моего собственного опыта, на iOS, нажмите кнопку «Домой», нажмите кнопку питания, чтобы войти в спящий режим, Javascript приложения зависнет через 10 секунд. И они могут быть вызваны, когда ваше приложение вернется на передний план ... Вы должны проверить это

Более надежная реализация будет сохранять ссылку на таймер и отменять ее, когда приложение переходит в фоновый режим.

0 голосов
/ 14 ноября 2018

Вы должны использовать состояние приложения для этого случая вот пример кода, который я использовал

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>
    );
  }

}
...