如何清除应用程序处于后台状态反应本机的间隔?
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 秒内被冻结。当您的应用程序返回前台时,它们可能会被调用...您应该测试一下
一个更健壮的实现会保持对计时器的引用,并在应用程序进入后台时取消它。
我有一个组件每 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 秒内被冻结。当您的应用程序返回前台时,它们可能会被调用...您应该测试一下
一个更健壮的实现会保持对计时器的引用,并在应用程序进入后台时取消它。