Retrofit2 中不断出现 java.io.InterruptedIOException: 超时

问题描述 投票:0回答:2

我很少在办公室得到

java.io.InterruptedIOException: timeout

然而,这种情况在商店里不断发生。

所以,我设定了

client.addInterceptor(httpLoggingInterceptor)
            .connectTimeout(5, TimeUnit.SECONDS)
            .callTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)

但是,这不起作用。

那么,我在 .enqueue() 中做了什么

fun startPay(){
    // ... Service Generator and so on...
    override fun onFailure(call: Call<ResultData>, t: Throwable) {
        when(t){
            is InterruptedIOException ->{
                Thread.sleep(1000)
                startPay()
            }
            else->{
                Toast.makeText(this, t.toString(), Toast.LENGTH_SHORT).show()
            }
        }
    }
}

我猜测发生这种情况是因为短时间内点击超过两次,或者我在 200 次响应后连续拨打 3 次。前任。 A 调用 -> 200 响应 -> B 调用 -> 200 响应 -> C 调用 -> 200 响应 -> UI 更新。 现在,它捕获异常并重试 api 调用。我认为这没有理由被同一个线程或其他线程中断..

这个解决方案总体来说还不错。但问题是当我付款时它必须只调用一次。

这个

InterrupedIOException: timeout
(不是SocketTimeout)似乎在从服务器获得响应之前取消了连接,服务器正在很好地发送响应并且没有问题。

stackoverflow 中的一些问题提到了 Crashlystics。我正在使用它,但我不应该删除它。

我正在使用:

    // Firebase
    // Import the BoM for the Firebase platform
    implementation platform('com.google.firebase:firebase-bom:26.0.0')
    implementation 'com.google.firebase:firebase-core'
    implementation 'com.google.firebase:firebase-auth'
    implementation 'com.google.firebase:firebase-auth-ktx'
    implementation 'com.google.firebase:firebase-config' // remote config
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-analytics-ktx'
    implementation 'com.google.firebase:firebase-crashlytics'
    implementation 'com.google.firebase:firebase-perf'
    implementation 'com.google.firebase:firebase-config-ktx'

    // Network
    // okhttp: https://github.com/square/okhttp
    implementation 'com.squareup.okhttp3:okhttp:4.7.2'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation 'org.conscrypt:conscrypt-android:2.2.1' // optional

错误在这里:

java.io.InterruptedIOException: timeout
W/System.err: java.io.InterruptedIOException: timeout
W/System.err:     at okhttp3.internal.connection.RealCall.timeoutExit(RealCall.kt:384)
W/System.err:     at okhttp3.internal.connection.RealCall.maybeReleaseConnection(RealCall.kt:346)
W/System.err:     at okhttp3.internal.connection.RealCall.noMoreExchanges$okhttp(RealCall.kt:310)
W/System.err:     at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:205)
W/System.err:     at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:502)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W/System.err:     at java.lang.Thread.run(Thread.java:761)
W/System.err: Caused by: java.io.IOException: Canceled
W/System.err:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:72)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:219)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at com.example.helper.api.ServiceGenerator$createService$$inlined$-addInterceptor$1.intercept(Interceptor.kt:87)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
W/System.err:   ... 4 more
android https timeout retrofit2 timeoutexception
2个回答
1
投票

可能的原因之一是 okhttp3 中的错误。当您设置超时后,在 IPv6 网络下 POST 请求可能会被取消,并显示如上所述的日志。我可以使用 IPv6Droid 应用程序来重现它进行测试(它不是免费的)。

要修复它,只需删除

.callTimeout()


0
投票

如果还需要callTimeout,可以添加自定义Interceptor:

class InterruptedIOExceptionInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        return try {
            chain.proceed(chain.request())
        } catch (e: InterruptedIOException) {
            Response.Builder()
                .code(408)
                .message("Request Timeout")
                .protocol(Protocol.HTTP_1_1) //fixme hardcoded protocol
                .request(chain.request())
                .body("Request Timeout".toResponseBody("text/html".toMediaTypeOrNull()))
                .build()
        }
    }
}

将其添加到OkHttpClient.Builder中:

okHttpClient.addInterceptor(InterruptedIOExceptionInterceptor())
© www.soinside.com 2019 - 2024. All rights reserved.