在日常的Android功能开发中,我们难免会碰到需要定时任务功能,例如定时轮询某个接口,或者是每隔多长时间检查一次本地数据,在本文中,主要介绍android中常用的两种定时任务实现方式
- 使用Handler实现
- 使用RxJava实现
一、使用Handler实现定时任务
Handler实现定时任务的原理是通过不断的发送延迟消息实现,对handler实现定时任务进行简单封装工具类如下:
/**
* 轮询工具类(Handler实现)
*/
public class PollingUtil {
private Handler mHanlder;
private Map<Runnable, Runnable> mTaskMap = new HashMap<Runnable, Runnable>();
public PollingUtil(Handler handler) {
mHanlder = handler;
}
/**
* 开启定时任务
* @param runnable 任务
* @param interval 时间间隔
*/
public void startPolling(Runnable runnable, long interval) {
startPolling(runnable, interval, false);
}
/**
* 开启定时任务
* @param runnable 任务
* @param interval 时间间隔
* @param runImmediately 是否先立即执行一次
*/
public void startPolling(final Runnable runnable, final long interval,
boolean runImmediately) {
if (runImmediately) {
runnable.run();
}
Runnable task = mTaskMap.get(runnable);
if (task == null) {
task = new Runnable() {
@Override
public void run() {
runnable.run();
post(runnable, interval);
}
};
mTaskMap.put(runnable, task);
}
post(runnable, interval);
}
/**
* 结束某个定时任务
* @param runnable 任务
*/
public void endPolling(Runnable runnable) {
if (mTaskMap.containsKey(runnable)) {
mHanlder.removeCallbacks(mTaskMap.get(runnable));
}
}
private void post(Runnable runnable, long interval) {
Runnable task = mTaskMap.get(runnable);
mHanlder.removeCallbacks(task);
mHanlder.postDelayed(task, interval);
}
}
- 开启定时任务
//每3秒打印一次日志
PollingUtil pollingUtil = new PollingUtil(new Handler(getMainLooper()));
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.e("MainActivity", "----------handler 定时轮询任务----------");
}
};
pollingUtil.startPolling(runnable, 3000, true);
- 停止定时任务
pollingUtil.endPolling(runnable);
二、使用RxJava实现定时任务
RxJava实现定时任务主要通过 interval 方法:
interval(long initialDelay, long period, TimeUnit unit)
interval(long period, TimeUnit unit)
参数解释:
- initialDelay:首次执行任务延迟多少
- period:定时任务时间间隔
- unit:时间单位
下面代码是实现每隔3秒打印一次日志,首次执行任务不延迟:
Disposable disposable = Observable.interval(0, 3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.e("MainActivity", "----------RxJava 定时轮询任务----------");
}
});
然后可以通过调用Disposable 的disposable ()方法停止轮询:
disposable.dispose();
运行结果如下:
三、总结
以上介绍的两种方式是项目中比较常用的实现定时任务的方式,并且在测试的过程中发现了一个很奇怪的问题,就是这两种方式在模拟器上运行的时候都只是刚开始的回调时间比较准确,到第四五次之后就出现很久才回调的情况,但是在真机上测试这两种方式回调时间都是准确的,这里可能是模拟器出现的问题。