Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
205 views
in Technique[技术] by (71.8m points)

android - Retrofit custom timeout is not working properly

I have a client that performs n number of retries with a specific timeout, when I perform the tests in the emulator, it is always taking 40 seconds per retry, or even more, the time I have configured is 5 seconds.

I performed a test by commenting on these three lines:

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

Expecting it to take the default timeout (10 seconds) sometimes the result was correct (10 seconds), after several executions the time no longer matches.

Also perform the test on a physical device and the same thing happens.

Any idea what is happening?

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()

    }


}}
question from:https://stackoverflow.com/questions/65893873/retrofit-custom-timeout-is-not-working-properly

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You should read up on https://www.baeldung.com/okhttp-timeouts

Most likely you want to use callTimeout to control a single timeout for the whole call. With connection reuse the connect, read and write timeouts often don't trigger due to other requests on the same underlying IO socket.

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

Also the event listener will often give you better understanding that the request interceptor https://square.github.io/okhttp/events/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...