React Native应用后台运行时如何保持Redux Saga正常响应
问题核心原因
你的问题本质是App切后台后JS线程被系统挂起,导致redux-saga的重连逻辑、定时器无法正常执行:
- 你当前
@mauron85/react-native-background-geolocation的配置中startForeground为false,Android系统会在App退后台数分钟后冻结JS线程,所有JS侧的事件监听、延迟任务都会停止运行 - 现有重连逻辑仅依赖socket断开事件、ping超时触发,后台线程冻结后这些触发逻辑都无法执行,哪怕网络恢复也不会主动重连
解决方案
1. 开启后台定位前台服务保活
修改定位库配置,开启前台服务,在后台显示常驻通知,避免JS线程被系统冻结:
BackgroundGeolocation.configure({ desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY, stationaryRadius: 1, distanceFilter: 1, notificationTitle: '轨迹上报运行中', notificationText: '应用正在后台上报位置信息', notificationIcon: 'mipmap/ic_launcher', // 替换为你的应用通知图标 debug: false, startOnBoot: false, url: null, stopOnTerminate: true, locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER, interval: 1000, fastestInterval: 1000, activitiesInterval: 1000, startForeground: true, // 改为true开启前台服务 stopOnStillActivity: false });
iOS端还需要在Xcode的Signing & Capabilities中添加Background Modes能力,勾选Location updates和Background fetch。
2. 新增重连触发逻辑
现有重连触发条件覆盖不全,新增两个触发场景:
- 每次收到定位事件时检查socket状态,若未连接则主动触发重连,因为后台定位事件是原生侧触发的,不受JS线程冻结影响,只要位置更新就会执行回调
BackgroundGeolocation.on('location', (location) => { dispatch(onLocationChange({ latitude: location.latitude, longitude: location.longitude })); // 新增socket状态检查,断连则触发重连 const socketState = store.getState().routeSocket.readyState; // 你需要在redux中存储socket的连接状态 if (socketState !== WebSocket.OPEN) { dispatch({ type: 'ROUTE_SOCKET_RETRY_ACTION_TYPE' }); } });
- 引入网络状态监听,网络从断开恢复为连接时主动触发重连:
安装@react-native-community/netinfo监听网络变化,网络恢复时dispatchNETWORK_CONNECTED事件,在RouteSocketSaga的监听事件数组中新增该事件:
const routeSocketAction = yield take([ 'DB_INITIALIZED', PERSIST_REHYDRATE, ON_AUTH_CHANGE, 'ROUTE_SOCKET_RETRY_ACTION_TYPE', 'NETWORK_CONNECTED' // 新增网络恢复事件触发重连 ]);
3. 优化saga重连逻辑
现有重连的延迟依赖saga delay,后台运行时可能出现计时不准的问题,你可以将重连延迟改为:如果当前重试是后台状态,就跳过固定延迟直接尝试重连,或者缩短后台重试的间隔。
内容的提问来源于stack exchange,提问作者Tzvetlin Velev
相关产品推荐
相关产品推荐

