我很少在办公室得到
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
可能的原因之一是 okhttp3 中的错误。当您设置超时后,在 IPv6 网络下 POST 请求可能会被取消,并显示如上所述的日志。我可以使用 IPv6Droid 应用程序来重现它进行测试(它不是免费的)。
要修复它,只需删除
.callTimeout()
。
如果还需要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())