OkHttp(Retrofit)對于http狀態碼202的處理

http code 202 :
The request has been accepted for processing, but the processing has not been completed.

這時候,服務器給你的body是空的,如果你使用去解析為json,那么,恭喜你

java.io.EOFException: End of input at line 1 column 1 在前面等著你

一個比較好的理解就是,服務器接受了你的請求,但是現在來不及處理,需要你等會試試。對于這種狀態碼,OkHttp并沒有為我們處理,jake大神也回答如是:

Paste_Image.png

這個issue在這里:
https://github.com/square/retrofit/issues/1554

我個人的解決辦法是如此:

  • 寫一個攔截器,攔截這種202的狀態碼.
  • 然后我們本身又使用的rxjava這個強大的框架去配合Retrofit,這時候,我遇到這種狀態嗎的是時候,去重試即可,具體的攔截器如下:

public class CreateInterceptor implements Interceptor {
    public static final int HTTP_CODE_ACCEPT = 202;                     //請求成功,但沒有處理

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());  //如果401了,會先執行TokenAuthenticator

        Logger.e("CreateInterceptor request url "+response.request().url());
        Logger.e("CreateInterceptor  response code "+response.code());
        if (response.code() == HTTP_CODE_ACCEPT) {
            CreateInterceptorExceptioin interceptorExceptioin = new CreateInterceptorExceptioin();

            interceptorExceptioin.setErrorCode(HTTP_CODE_ACCEPT);
            interceptorExceptioin.setRetry_after(response.header("Retry-After"));
            throw  interceptorExceptioin;
        }
        return response;
    }



    public class CreateInterceptorExceptioin extends Error{
        private int errorCode;
        private String retry_after;


        public int getErrorCode() {
            return errorCode;
        }

        public void setErrorCode(int errorCode) {
            this.errorCode = errorCode;
        }

        public String getRetry_after() {
            return retry_after;
        }

        public void setRetry_after(String retry_after) {
            this.retry_after = retry_after;
        }
    }

}

然后,在build的時候

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new CreateInterceptor());//攔截202,直接返回錯誤哦
OkHttpClient okHttpClient = builder.build();

再將上述 build出來的OkHttpClient 設置給 Retrofit 即可。

new Retrofit.Builder().client(....)...

那么,最最重要的,如何去重試呢?

實際上,我也是參考了網上的一個例子 ,在我的另外一篇文章中有提到這個技巧:android中使用Rxjava一些有意思的代碼集合 ,在第17條那里,參照這個原理,略微改了改,這里的代碼如下:

public static final class RetryWhen202Happen implements Func1<Observable<? extends Throwable>, Observable<?>> {

        private final int _maxRetries;
        private final int _retryDelayMillis;
        private       int _retryCount;

        public RetryWhen202Happen(final int maxRetries, final int retryDelayMillis) {
            _maxRetries = maxRetries;
            _retryDelayMillis = retryDelayMillis;
            _retryCount = 0;
        }

        @Override
        public Observable<?> call(Observable<? extends Throwable> inputObservable) {
            return inputObservable.flatMap(new Func1<Throwable, Observable<?>>() {
                @Override
                public Observable<?> call(Throwable throwable) {
                    if (++_retryCount < _maxRetries && throwable instanceof CreateInterceptor.CreateInterceptorExceptioin) {
                        // When this Observable calls onNext, the original
                        // Observable will be retried (i.e. re-subscribed)
                        Log.e("RetryWhen202Happen", "call: "+_retryCount);
                        return Observable.timer(_retryCount * _retryDelayMillis, TimeUnit.MILLISECONDS);
                    }
                    return Observable.error(throwable);
                }
            });
        }
    }

最后:我們使用rxjava提供的retryWhen即可。

retryWhen.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容