废话不多说直接上代码:
public class RxCountDown {
public static Observable countdown(int time) {
if (time < 0) time = 0;
final int countTime = time;
return Observable.interval(0, 1, TimeUnit.SECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1() {
@Override
public Integer call(Long increaseTime) {
return countTime - increaseTime.intValue();
}
})
.take(countTime + 1);
}
}
代码比较简单,利用 interval() 定时发送 Observable ,通过 map() 将 0、1、2、3... 的计数变为 ...3、2、1、0 倒计时。通过 take() 取 >=0 的 Observable 。
使用时:
RxCountDown.countdown(5)
.doOnSubscribe(new Action0() {
@Override
public void call() {
appendLog("开始计时");
}
})
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
appendLog("计时完成");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
appendLog("当前计时:" + integer);
}
});
这样就实现了一个5秒的倒计时。
运行结果:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
WTF…… 5 与 4 怎么同时执行了!反倒是 doOnSubscribe() 与 计时5 之间有1秒的间隔,很明显有BUG。
这么几行代码找了1个小时没找到问题在哪里……后来尝试着把 .subscribeOn(AndroidSchedulers.mainThread()) 删除,然后又运行了一下:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
D/HIDETAG:
居然正确了,倒计时正常工作了……
不知道是 Rx 的BUG还是我漏掉了什么知识, 为什么指定 subscribe 的线程为主线程会导致第一次计时不准确?
希望有知道的不吝赐教。
2016.2.16更新:找到原因了,不是Rx的锅,是我自己编译环境的问题……