1. 程式人生 > >RxJava retryWhen操作符實現錯誤重試機制

RxJava retryWhen操作符實現錯誤重試機制

業務需求

當我們在app裡發起網路請求時,可能會因為各種問題導致失敗。如何利用RxJava來實現出現錯誤後重試若干次,並且可以設定重試的時間間隔。

具體實現

網路請求使用Retrofit來做,請求使用者資訊介面

@GET("/userinfo?noToken=1")
    Observable<Response> getUserInfoNoToken();

請求使用者資訊介面的邏輯程式碼

userApi.getUserInfoNoToken()
                        //總共重試3次,重試間隔3000毫秒
                        .retryWhen(new
RetryWithDelay(3, 3000)) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(new Action1<Response>() { @Override public void call(Response response) { String content = new
String(((TypedByteArray) response.getBody()).getBytes()); printLog(tvLogs, "", content); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { throwable.printStackTrace(); } });

RetryWithDelay程式碼:

public class RetryWithDelay implements
            Func1<Observable<? extends Throwable>, Observable<?>> {

        private final int maxRetries;
        private final int retryDelayMillis;
        private int retryCount;

        public RetryWithDelay(int maxRetries, int retryDelayMillis) {
            this.maxRetries = maxRetries;
            this.retryDelayMillis = retryDelayMillis;
        }

        @Override
        public Observable<?> call(Observable<? extends Throwable> attempts) {
            return attempts
                    .flatMap(new Func1<Throwable, Observable<?>>() {
                        @Override
                        public Observable<?> call(Throwable throwable) {
                            if (++retryCount <= maxRetries) {
                                // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed).
                                printLog(tvLogs, "", "get error, it will try after " + retryDelayMillis
                                        + " millisecond, retry count " + retryCount);
                                return Observable.timer(retryDelayMillis,
                                        TimeUnit.MILLISECONDS);
                            }
                            // Max retries hit. Just pass the error along.
                            return Observable.error(throwable);
                        }
                    });
        }
    }

如何模擬重試呢?

方法一:把伺服器關閉,關閉伺服器後,客戶端請求介面的必然會報錯,看看是不是重試三次。

執行輸出:

'get error, it will try after 3000 millisecond, retry count 1'
Main Thread:false, Thread Name:Retrofit-Idle

'get error, it will try after 3000 millisecond, retry count 2'
Main Thread:false, Thread Name:Retrofit-Idle

'get error, it will try after 3000 millisecond, retry count 3'
Main Thread:false, Thread Name:Retrofit-Idle

上面是重試三次了,但是我們怎麼知道,如果在伺服器啟動後,在接下的重試中請求成功呢?接下來試試方法二。

方法二:先把伺服器關閉,當點選按鈕請求的同時,啟動Tomcat伺服器。

執行輸出:

'get error, it will try after 3000 millisecond, retry count 1'
Main Thread:false, Thread Name:Retrofit-Idle

'get error, it will try after 3000 millisecond, retry count 2'
Main Thread:false, Thread Name:Retrofit-Idle

'username:chiclaim,age:007'
Main Thread:true, Thread Name:main

可以發現,在第三次重試的時候,伺服器可用了。