Модифицированный пользовательский тайм-аут не работает должным образом

#android #kotlin #retrofit #retrofit2 #okhttp

#Android #kotlin #модифицированный #retrofit2 #okhttp

Вопрос:

У меня есть клиент, который выполняет n попыток с определенным таймаутом, когда я выполняю тесты в эмуляторе, на каждую попытку всегда уходит 40 секунд или даже больше, время, которое я настроил, составляет 5 секунд.

Я выполнил тест, прокомментировав эти три строки:

  .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
 .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
 .readTimeout(TIMEOUT, TimeUnit.SECONDS)
 

Ожидая, что он займет время ожидания по умолчанию (10 секунд) иногда результат был правильным (10 секунд), после нескольких выполнений время больше не совпадает.

Также выполните тест на физическом устройстве, и произойдет то же самое.

Есть идеи, что происходит?

 object Client {

private const val PATTERN = "0000"
private const val S_TAG = "{SN}"
private const val C_TAG = "{CC}"

/**
 * Retrofit Builder is created
 * @param sNbr
 * @param cCode
 * @return Retrofit
 */
private fun createRetrofitBuilder(
    sNbr: String,
    cCode: String
): Retrofit {
    val builder = Retrofit.Builder().baseUrl(
        getServer(
            sNbr,
            cCode))
        .client(CertificateValidation.getUnsafeOkHttpClient())
        .addConverterFactory(SimpleXmlConverterFactory.create())

    return builder.build()
}

/**
 * Gets URL of request.
 * @param sNbr
 * @param cCode
 * @return server
 */
private fun getServer(sNbr: String, cCode: String): String {
    var server = Constants.URL_SERVICE
    server = server.replace(S_TAG,
        getStString(
            storeNbr
        )
    )
    server = server.replace(C_TAG, countryCode)
    return server
}

/**
 * 
 */
private fun getStString(sNbr: String): String {
    val decimalFormat = DecimalFormat(PATTERN)
    return decimalFormat.format(sNbr.toInt())
}

/**
 * @param serviceType
 * @return T
 */
fun <T> buildService(
    serviceType: Class<T>,
    sNbr: String,
    cCode: String
): T {
    return createRetrofitBuilder(
        sNbr,
        cCode
    ).create(serviceType)
}}
 

CertificateValidation.kt

 class CertificateValidation {
companion object {


    private const val TIMEOUT: Long = 5

    /**
     * Method that validates the SSL certificate sent from the Service.
     */
    fun getUnsafeOkHttpClient(): OkHttpClient {

        // Create a trust manager that does not validate certificate chains
        val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
            @SuppressLint("TrustAllX509TrustManager")
            @Throws(CertificateException::class)
            override fun checkClientTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            @SuppressLint("TrustAllX509TrustManager")
            @Throws(CertificateException::class)
            override fun checkServerTrusted(
                chain: Array<java.security.cert.X509Certificate>,
                authType: String
            ) {
            }

            override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
                return arrayOf()
            }
        })

        // Install the all-trusting trust manager
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustAllCerts, java.security.SecureRandom())
        // Create an ssl socket factory with our all-trusting manager
        val sslSocketFactory = sslContext.socketFactory

        val builder = OkHttpClient.Builder()
           .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(TIMEOUT, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .connectionSpecs(
                listOf(
                    ConnectionSpec.COMPATIBLE_TLS,
                    ConnectionSpec.CLEARTEXT
                )
            )

        builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)

        return builder.build()

    }


}}
 

Ответ №1:

Вы должны прочитать https://www.baeldung.com/okhttp-timeouts

Скорее всего, вы хотите использовать callTimeout для управления одним таймаутом для всего вызова. При повторном использовании соединения тайм-ауты подключения, чтения и записи часто не срабатывают из-за других запросов в том же базовом сокете ввода-вывода.

     OkHttpClient client = new OkHttpClient.Builder()
      .callTimeout(10, TimeUnit.SECONDS)
      .build();
 

Кроме того, прослушиватель событий часто дает вам лучшее представление о том, что перехватчик запросов https://square.github.io/okhttp/events /