1. 程式人生 > >用RxJava實現倒計時與踩坑

用RxJava實現倒計時與踩坑

廢話不多說直接上程式碼:

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()>=0Observable

使用時:

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: <--  當前時間:0758628 --- 開始計時  -->
D/HIDETAG: <--  當前時間:0759646 --- 當前計時:5  -->
D/HIDETAG: <--  當前時間:0759647 --- 當前計時:4  -->
D/HIDETAG: <--  當前時間:0800646 --- 當前計時:3  -->
D/HIDETAG: <--  當前時間:0801646 --- 當前計時:2  -->
D/HIDETAG: <--  當前時間:0802645 --- 當前計時:1  -->
D/HIDETAG: <--  當前時間:0803646 --- 當前計時:0  -->
D/HIDETAG: <--  當前時間:0803650 --- 計時完成  -->

WTF……54怎麼同時執行了!反倒是doOnSubscribe()計時5之間有1秒的間隔,很明顯有BUG。

這麼幾行程式碼找了1個小時沒找到問題在哪裡……後來嘗試著把.subscribeOn(AndroidSchedulers.mainThread())刪除,然後又運行了一下:

D/HIDETAG: <--  當前時間:1458142 --- 開始計時  -->
D/HIDETAG: <--  當前時間:1458162 --- 當前計時:5  -->
D/HIDETAG: <--  當前時間:1459163 --- 當前計時:4  -->
D/HIDETAG: <--  當前時間:1500150 --- 當前計時:3  -->
D/HIDETAG: <--  當前時間:1501150 --- 當前計時:2  -->
D/HIDETAG: <--  當前時間:1502149 --- 當前計時:1  -->
D/HIDETAG: <--  當前時間:1503150 --- 當前計時:0  -->
D/HIDETAG: <--  當前時間:1503151 --- 計時完成  -->

居然正確了,倒計時正常工作了……
不知道是Rx的BUG還是我漏掉了什麼知識,為什麼指定subscribe的執行緒為主執行緒會導致第一次計時不準確?
希望有知道的不吝賜教。

2016.2.16更新:找到原因了,不是Rx的鍋,是我自己編譯環境的問題……



文/Hideeee(簡書作者)
原文連結:http://www.jianshu.com/p/17af7790e8a6
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。