一、场景
我们现在有个场景,每隔 2 分钟做一次 A 工作,每隔 5 分钟做一次 B 工作,每隔 10 秒做一次 C 工作。
二、限制
在 React Native 里不管是 setTimeout,setInterval 都不能超过 60 秒,哪怕是多 1 秒都会给出警告
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setInterval with duration 61000ms)
三、方案
有了这个限制之后,我们就只能另辟蹊径了,随后找到了 react-native-background-timer
。
这个控件从原生入手,使用 Handler
+ Runnable
来实现(Android 端),并且还用了电池管理(PowerManager)里的唤醒机制,保证 App 切到后台也能正常工作。
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
if (!wakeLock.isHeld()) wakeLock.acquire();
...
四、实战
import BackgroundTimer from 'react-native-background-timer';
4.1 最简单的使用(for Android)
useEffect(() => {
const intervalId = BackgroundTimer.setInterval(() => {
deviceCheck();
}, 5 * 60 * 1000);
return () => {
BackgroundTimer.clearInterval(intervalId);
};
}, []);
注:上面这段代码 clearInterval 只有在页面 pop 出 stack 的时候才会执行。 如果你需要主动 clear 掉这个 interval,就需要把clearInterval写在可以手动触发的地方。
如果你想要用 setTimeout ,只需要把上述 Interval 换成 setTimeout 即可。
4.2 写跨平台的代码(Android 和 iOS)
useEffect(() => {
BackgroundTimer.runBackgroundTimer(() => {
someRequest();
}, 2 * 60 * 1000);
return () => {
BackgroundTimer.stopBackgroundTimer()
};
}, []);
五、小结
目前这个方案在我们项目里运用的还比较稳定,如果大家有不同方案,欢迎留言讨论!