用RxJava實現倒計時與踩坑
阿新 • • 發佈:2019-02-09
廢話不多說直接上程式碼:
public class RxCountDown {
public static Observable<Integer> 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<Long, Integer>() {
@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<Integer>() {
@Override
public void onCompleted() {
appendLog("計時完成");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Integer integer) {
appendLog("當前計時:" + integer);
}
});
這樣就實現了一個5秒的倒計時。
執行結果:
D/HIDETAG: <-- 當前時間:07分58秒628 --- 開始計時 -->
D/HIDETAG: <-- 當前時間:07分59秒646 --- 當前計時:5 -->
D/HIDETAG: <-- 當前時間:07分59秒647 --- 當前計時:4 -->
D/HIDETAG: <-- 當前時間:08分00秒646 --- 當前計時:3 -->
D/HIDETAG: <-- 當前時間:08分01秒646 --- 當前計時:2 -->
D/HIDETAG: <-- 當前時間:08分02秒645 --- 當前計時:1 -->
D/HIDETAG: <-- 當前時間:08分03秒646 --- 當前計時:0 -->
D/HIDETAG: <-- 當前時間:08分03秒650 --- 計時完成 -->
WTF……5
與4
怎麼同時執行了!反倒是doOnSubscribe()
與計時5
之間有1秒的間隔,很明顯有BUG。
這麼幾行程式碼找了1個小時沒找到問題在哪裡……後來嘗試著把.subscribeOn(AndroidSchedulers.mainThread())
刪除,然後又運行了一下:
D/HIDETAG: <-- 當前時間:14分58秒142 --- 開始計時 -->
D/HIDETAG: <-- 當前時間:14分58秒162 --- 當前計時:5 -->
D/HIDETAG: <-- 當前時間:14分59秒163 --- 當前計時:4 -->
D/HIDETAG: <-- 當前時間:15分00秒150 --- 當前計時:3 -->
D/HIDETAG: <-- 當前時間:15分01秒150 --- 當前計時:2 -->
D/HIDETAG: <-- 當前時間:15分02秒149 --- 當前計時:1 -->
D/HIDETAG: <-- 當前時間:15分03秒150 --- 當前計時:0 -->
D/HIDETAG: <-- 當前時間:15分03秒151 --- 計時完成 -->
居然正確了,倒計時正常工作了……
不知道是Rx
的BUG還是我漏掉了什麼知識,為什麼指定subscribe
的執行緒為主執行緒會導致第一次計時不準確?
希望有知道的不吝賜教。
2016.2.16更新:找到原因了,不是Rx的鍋,是我自己編譯環境的問題……
文/Hideeee(簡書作者)
原文連結:http://www.jianshu.com/p/17af7790e8a6
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。