#kotlin #retrofit
Вопрос:
Я протестировал свое приложение на физических устройствах, и когда я переключаюсь между действиями, я делаю 3 запроса на свой сервер для повторного получения данных и обновления своей локальной базы данных (этот сервер построен с использованием kotlin и Ktor) и инициализирую наблюдаемое, когда все данные обновляются, а другое действие выполняет 1 запрос на другой сервер (PHP-сервер). Этот запрос только извлекает данные и показывает на RecyclerView, данные не хранятся в локальной базе данных. У меня есть два разных экземпляра дооснащения для серверов call this (эти экземпляры статичны и являются одноэлементными экземплярами).
Когда я быстро переключаюсь между этими действиями, до определенного времени вызовы с сервера ktor блокируются и вызывают исключение java.net.SocketTimeoutException: тайм-аут, и не удается восстановить соединение с сервера (подключиться с сервера ktor можно только при выключении/включении Wi-Fi).
Сначала я подумал, что это была ошибка сервера Ktor, потому что все устройства локальной сети, использующие приложение, также не могут подключиться с сервера ktor, но в журналах сервера не отображается никаких ошибок.
Это исключение, которое показывает IDE Logcat для Android Studio:
2021-09-01 18:40:09.534 W/System.err: Caused by: java.net.SocketTimeoutException: timeout
2021-09-01 18:40:09.534 W/System.err: at okio.SocketAsyncTimeout.newTimeoutException(JvmOkio.kt:143)
2021-09-01 18:40:09.534 W/System.err: at okio.AsyncTimeout.access$newTimeoutException(AsyncTimeout.kt:162)
2021-09-01 18:40:09.535 W/System.err: at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:335)
2021-09-01 18:40:09.535 W/System.err: at okio.RealBufferedSource.indexOf(RealBufferedSource.kt:427)
2021-09-01 18:40:09.535 W/System.err: at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:320)
2021-09-01 18:40:09.535 W/System.err: at okhttp3.internal.http1.HeadersReader.readLine(HeadersReader.kt:29)
2021-09-01 18:40:09.536 W/System.err: at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:178)
2021-09-01 18:40:09.536 W/System.err: at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:106)
2021-09-01 18:40:09.536 W/System.err: at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:79)
2021-09-01 18:40:09.536 W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-09-01 18:40:09.536 W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
2021-09-01 18:40:09.537 W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-09-01 18:40:09.537 W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
2021-09-01 18:40:09.537 W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-09-01 18:40:09.537 W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
2021-09-01 18:40:09.537 W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-09-01 18:40:09.538 W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
2021-09-01 18:40:09.538 W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
2021-09-01 18:40:09.538 W/System.err: at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
2021-09-01 18:40:09.538 W/System.err: ... 4 more
2021-09-01 18:40:09.539 W/System.err: Caused by: java.net.SocketException: Socket closed
2021-09-01 18:40:09.540 W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:209)
2021-09-01 18:40:09.540 W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:144)
2021-09-01 18:40:09.540 W/System.err: at okio.InputStreamSource.read(JvmOkio.kt:90)
2021-09-01 18:40:09.540 W/System.err: at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:129)
Это мой как модифицированный экземпляр, так и клиенты, весь этот код находится внутри сопутствующего объекта:
fun getKtorConfig(ctx: Context): Retrofit? = ktorRetrofit ?: try {
synchronized(this) {
ktorRetrofit = Retrofit.Builder()
.baseUrl(
"http://" SharedPreferencesManager.getKtorWebService(ctx) ":"
SharedPreferencesManager.getKtorWebServicePort(ctx) "/appservice/"
)
.addConverterFactory(GsonConverterFactory.create())
.client(getClient())
.build()
ktorRetrofit
}
} catch (e: Exception) {
Log.d(Tags.ACCOUNT_DETAILS_TAG, "ERROR EN EL GET KTOR RETROFIT CONFIG")
ktorRetrofit = null
getKtorConfig(ctx)
}
fun getPhpConfig(ctx: Context): Retrofit? = phpRetrofit ?: try {
synchronized(this) {
phpRetrofit = Retrofit.Builder()
.baseUrl("http://" SharedPreferencesManager.getPHPWebService(ctx) ":"
SharedPreferencesManager.getPHPWebServicePort(ctx) "/webservice/api/v1/")
.addConverterFactory(GsonConverterFactory.create())
.client(getClient())
.build()
phpRetrofit
}
} catch (e: Exception) {
Log.d(Tags.ACCOUNT_DETAILS_TAG, "ERROR EN EL GET DE PHP RETROFIT CONFIG")
phpRetrofit = null
getPhpConfig(ctx)
}
// Retrofit client
private fun getClient(): OkHttpClient = OkHttpClient.Builder()
.dispatcher(Dispatcher().apply {
maxRequests = 5000
maxRequestsPerHost = 1000
})
.connectTimeout(40, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(60, TimeUnit.SECONDS)
.followRedirects(false)
.retryOnConnectionFailure(true)
.build()
This is my gradle libraries:
// Retrofit
def retrofit_version = "2.9.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
Примечания:
Два сервера находятся в локальной сети, и серверы работают по протоколу http, а не https, я настроил манифест и создаю network-security-config.xml для разрешения http-запросов.
Примечание 2: В действии, в котором у меня есть 3 запроса к серверу ktor, каждый запрос выполняется после завершения последнего запроса и не может переключиться на другое действие, пока не будет завершен весь запрос.
Есть какие-нибудь идеи по поводу того, что это за приложение?
С уважением.