12
public class Router {

    ...

    private static Retrofit retrofit = null;

    ...

    public Retrofit getRetrofit() {
        if (retrofit == null) {

            ...

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl("***")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }

    ...

}

I setup timeout in OkHttpClient. Now there is a API needs different timeout.

How can i do?

Is there something like this?

@Timeout
Observable<ResponseBody> exapmle(@Timeout("connect") int connect
 , @Timeout("read") int read
 , @Timeout("write") int write);
2
  • y you want to increase timeout? Is there any exception or error ? Commented Nov 17, 2017 at 9:46
  • there is a api to upload a large file. Commented Nov 17, 2017 at 9:48

4 Answers 4

33

enter image description here

Thanks a lot.

here is my code:

public static final String CONNECT_TIMEOUT = "CONNECT_TIMEOUT";
public static final String READ_TIMEOUT = "READ_TIMEOUT";
public static final String WRITE_TIMEOUT = "WRITE_TIMEOUT";

...

Interceptor timeoutInterceptor = new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        int connectTimeout = chain.connectTimeoutMillis();
        int readTimeout = chain.readTimeoutMillis();
        int writeTimeout = chain.writeTimeoutMillis();

        String connectNew = request.header(CONNECT_TIMEOUT);
        String readNew = request.header(READ_TIMEOUT);
        String writeNew = request.header(WRITE_TIMEOUT);

        if (!TextUtils.isEmpty(connectNew)) {
            connectTimeout = Integer.valueOf(connectNew);
        }
        if (!TextUtils.isEmpty(readNew)) {
            readTimeout = Integer.valueOf(readNew);
        }
        if (!TextUtils.isEmpty(writeNew)) {
            writeTimeout = Integer.valueOf(writeNew);
        }

        return chain
                .withConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
                .withReadTimeout(readTimeout, TimeUnit.MILLISECONDS)
                .withWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS)
                .proceed(request);
    }
};

OkHttpClient httpClient = new OkHttpClient.Builder()
        .connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
        .writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
        .readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.MILLISECONDS)
        .addInterceptor(timeoutInterceptor)
        .build();

retrofit = new Retrofit.Builder()
        .baseUrl(Host.Develop.ACCOUNT_HOST)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .client(httpClient)
        .build();

...

example usage:

/**
 * check account status
 *
 * @param account
 * @return
 */
@Headers({"CONNECT_TIMEOUT:10000", "READ_TIMEOUT:10000", "WRITE_TIMEOUT:10000"})
@GET("login/prelogin")
Observable<ResponseBody> preLogin(@Query("account") String account);

or

/**
 * check account status
 * 
 * @param connectTimeout
 * @param readTimeout
 * @param writeTimeout
 * @param account
 * @return
 */
@GET("login/prelogin")
Observable<ResponseBody> preLogin(
        @Header("CONNECT_TIMEOUT") String connectTimeout,
        @Header("READ_TIMEOUT") String readTimeout,
        @Header("WRITE_TIMEOUT") String writeTimeout,
        @Query("account") String account);
Sign up to request clarification or add additional context in comments.

Comments

11

Kotlin

Interceptor

class TimeHeaderInterceptor : Interceptor {

    companion object {
        private const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
        private const val READ_TIMEOUT = "READ_TIMEOUT"
        private const val WRITE_TIMEOUT = "WRITE_TIMEOUT"
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        var connectTimeout = chain.connectTimeoutMillis()
        var readTimeout = chain.readTimeoutMillis()
        var writeTimeout = chain.writeTimeoutMillis()

        val builder = request.newBuilder()

        request.header(CONNECT_TIMEOUT)?.also {
            connectTimeout = it.toInt()
            builder.removeHeader(CONNECT_TIMEOUT)
        }

        request.header(READ_TIMEOUT)?.also {
            readTimeout = it.toInt()
            builder.removeHeader(READ_TIMEOUT)
        }

        request.header(WRITE_TIMEOUT)?.also {
            writeTimeout = it.toInt()
            builder.removeHeader(WRITE_TIMEOUT)
        }
        
        return chain
            .withConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
            .withReadTimeout(readTimeout, TimeUnit.MILLISECONDS)
            .withWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS)
            .proceed(builder.build())
    }
}

OkHttpClient

OkHttpClient.Builder()
            .connectTimeout(15_000, TimeUnit.MILLISECONDS)
            .writeTimeout(15_000, TimeUnit.MILLISECONDS)
            .readTimeout(15_000, TimeUnit.MILLISECONDS)
            .addInterceptor(TimeHeaderInterceptor()) // config
            .build()

HttpApiImpl

interface HttpApiImpl {

    /**
     * Dynamic configuration time, example
     *
     */
    @Headers("CONNECT_TIMEOUT:1000", "READ_TIMEOUT:5000", "WRITE_TIMEOUT:2000")
    @GET
    fun time(@Url url: String): Observable<String>
}

3 Comments

Hey what is this 15_000
15_000 It's a way of writing,1500 Millisecond
operations inside chain.run{} should be chained (as in Java implementation above). Otherwise only proceed() will take effect. See RealIncereptorChain
1

this is my Kotlin Version:

Interceptor

const val CONNECT_TIMEOUT = "CONNECT_TIMEOUT"
const val READ_TIMEOUT = "READ_TIMEOUT"
const val WRITE_TIMEOUT = "WRITE_TIMEOUT"

class TimeoutInterceptor : Interceptor {

    override fun intercept(chain: Chain): Response {
        val request: Request = chain.request()

        val connectTimeout =
            request.header(CONNECT_TIMEOUT)?.toInt() ?: chain.connectTimeoutMillis()
        val readTimeout = request.header(READ_TIMEOUT)?.toInt() ?: chain.readTimeoutMillis()
        val writeTimeout = request.header(WRITE_TIMEOUT)?.toInt() ?: chain.writeTimeoutMillis()

        return chain
            .withConnectTimeout(connectTimeout, MILLISECONDS)
            .withReadTimeout(readTimeout, MILLISECONDS)
            .withWriteTimeout(writeTimeout, MILLISECONDS)
            .proceed(request)
    }
}

OkHttpClient

OkHttpClient.Builder()
            .connectTimeout(15_000, TimeUnit.MILLISECONDS)
            .writeTimeout(15_000, TimeUnit.MILLISECONDS)
            .readTimeout(15_000, TimeUnit.MILLISECONDS)
            .addInterceptor(TimeoutInterceptor()) // config
            .build()

Api

interface Api {

    @Headers("$CONNECT_TIMEOUT:300000", "$READ_TIMEOUT:300000", "$WRITE_TIMEOUT:300000")
    @GET
    fun time(@Url url: String): Observable<String>
}

Comments

0

Create a new retrofit instance where you pass in timeout values as parameters.

public Retrofit getRetrofit(int connectionTimeout, int readWriteTimeout) {
        if (retrofit == null) {

            ...

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(connectionTimeout, TimeUnit.SECONDS)
                    .writeTimeout(readWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(readWriteTimeout, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl("***")
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
        return retrofit;
    }

There is no option like the below:

@Timeout
Observable<ResponseBody> exapmle(@Timeout("connect") int connect
                , @Timeout("read") int read
                , @Timeout("write") int write);

2 Comments

Is there a better solution without creating new instance?
Please specify whats the DEFAULT_WRITE_TIMEOUT

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.