簡體   English   中英

Retrofit:如何從 okhttp 攔截器再次重試請求?

[英]Retrofit: How do I retry the request again from okhttp interceptor?

我創建了一個攔截器。 在某些情況下,我想重試請求 'n' 次,我該怎么做?

class NetworkErrorHandler constructor():  Interceptor {

    //Central error handling block for errors which has impact all over the app
    override fun intercept(chain: Interceptor.Chain): Response {
        val request =  chain.request()
        var response = chain.proceed(request) 

        return  
            when (response.code) {
                401 -> { 
                    response
                }
                200 ->{  
                    response
                }
                else -> { 
                        var tryCount = 0
                        while (tryCount < 3) {
                            try { 
                                response = chain.proceed(request)
                                tryCount++
                            }catch (e: java.lang.Exception){
                                tryCount++
                            }
                        }  
                    response
                }
            } 
    }
}

它給了我這個錯誤:

Suppressed: java.lang.IllegalStateException: network interceptor must call proceed() exactly once

如果是,我是否必須在這里執行此操作,然后怎么做?

我認為您從另一個問題中引導自己如何使用 OkHttp/Retrofit 重試 HTTP 請求? (如果沒有,我建議你這樣做)。 您的代碼的問題是您的 while 僅受 trycount 的限制,而不受響應結果的限制。 嘗試在那里添加有關響應狀態的驗證,因此它不會並行執行 .proceed 方法兩次。

// try the request
Response response = chain.proceed(request);

int tryCount = 0;
while (!response.isSuccessful() && tryCount < 3) {

所以我能夠通過使用這條線從攔截器進行另一個調用

response.close()      
chain.call().clone().execute()
                

根據問題的完整代碼:

//Central error handling block for errors which has impact all over the app
class NetworkErrorHandler constructor(): Interceptor {

        var tryCount = 0
        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            var response = chain.proceed(request)

            return
            when(response.code) {
                401 - > {
                    response
                }
                200 - > {
                    response
                }
                else - > {

                    if (tryCount < 3) {
                        Thread.sleep(2000)
                        tryCount++
                        response.close()
                        chain.call().clone().execute()

                    }
                    response.newBuilder()
                    .code(401) // Whatever code
                    .body("".toResponseBody(null)) // Whatever body
                    .protocol(Protocol.HTTP_2)
                    .message("Network Error")
                    .request(chain.request())
                    .build()
                }
            }
        } 

這就是我的處理方式:

@Slf4j
public class HttpRetryInterceptor implements Interceptor {
    @Override
    public @NotNull Response intercept(Chain chain) throws IOException {
        log.error("Making request for the first time.");
        var request = chain.request();
        Response response = null;
        boolean responseOK = false;
        byte tryCount = 0;
        while (!responseOK && tryCount < 3) {
            try {
                Thread.sleep(5000 * tryCount);
                response = chain.proceed(request);
                log.info("Response is: {}",response);
                log.info("Response message: {}",response.message());
                responseOK = response.isSuccessful();

            }catch (Exception e){
                e.printStackTrace();
                log.error("Request was not successful: {} . Retrying." , tryCount);
            }finally{
                assert response != null;
                response.close();
                tryCount++;
            }
        }

        return response != null ? response : chain.proceed(request);
    }
}

然后我將我的攔截器添加到我的客戶端,如下所示: new OkHttpClient.Builder().addInterceptor(new HttpRetryInterceptor()).build()

借助Failsafe 的 OkHttp支持和適用於您的場景的 RetryPolicy,這非常容易:

RetryPolicy<Response> retryPolicy = RetryPolicy.<Response>builder()
  .handleResultIf(r -> r.code() != 401 && r.code() != 200)
  .withMaxAttempts(3)
  .build();
Call call = client.newCall(request);
FailsafeCall failsafeCall = FailsafeCall.with(retryPolicy).compose(call);

// Execute with retries
Response response = failsafeCall.execute();

使用.interceptors()來使用Application Interceptor而不是.networkInterceptors()允許多次調用.proceed() 在此處輸入圖像描述 更多信息: https ://square.github.io/okhttp/interceptors/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM