Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change timeout for a request in okhttp

Tags:

okhttp3

okhttp

In general we set timeout for the okHttp client and we use single instance of that client. So, we can't change the timeout for that client once it's generated.

How to change the timeout for a particular request ?? Is there anyway to do it without creating new client??

It's very common that some calls take more time atleast 1/2 per app, which needs more timeout than others. it would be great if request can override the default timeout.

like image 936
Ashok Varma Avatar asked Oct 20 '17 08:10

Ashok Varma


2 Answers

Updating to Retrofit 2.5.0 you can use Invocation class

New: Invocation class provides a reference to the invoked method and argument list as a tag on the underlying OkHttp Call. This can be accessed from an OkHttp interceptor for things like logging, analytics, or metrics aggregation.

In that way, you can create a SpecificTimeout annotation to be used only on the requests you need to set a different timeout duration and read its values on an OkHttp Interceptor to change the timeout at that point.

Custom Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SpecificTimeout {
    int duration();
    TimeUnit unit();
}

Service Interface

public interface GitHubService {
    @GET("/users")
    @SpecificTimeout(duration = 5000, unit = TimeUnit.MILLISECONDS)
    Call<List<User>> listUsers();

    @GET("/repos")
    @SpecificTimeout(duration = 15000, unit = TimeUnit.MILLISECONDS)
    Call<List<Repo>> listRepos();
}

Interceptor

class TimeoutInterceptor implements Interceptor {

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

        final Invocation tag = request.tag(Invocation.class);
        final Method method = tag != null ? tag.method() : null;
        final SpecificTimeout timeout = method != null ? method.getAnnotation(SpecificTimeout.class) : null;

        if (timeout != null) {
           return chain.withReadTimeout(timeout.duration(), timeout.unit())
                       .withConnectTimeout(timeout.duration(), timeout.unit())
                       .withWriteTimeout(timeout.duration(), timeout.unit())
                       .proceed(request);
        }

        return chain.proceed(request);
    }
}

OkHttp Builder

OkHttpClient okHttpClient = new OkHttpClient.Builder()
                //default timeout for not annotated requests
                .readTimeout(10000, TimeUnit.MILLISECONDS)
                .connectTimeout(10000, TimeUnit.MILLISECONDS)
                .writeTimeout(10000, TimeUnit.MILLISECONDS)
                .addInterceptor(new TimeoutInterceptor())
                .build();
like image 83
4 revs, 2 users 98% Avatar answered Oct 01 '22 06:10

4 revs, 2 users 98%


See https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PerCallSettings.java which creates shallow clones that only modify some settings.

// Copy to customize OkHttp for this request.
OkHttpClient client2 = client.newBuilder()
    .readTimeout(3000, TimeUnit.MILLISECONDS)
    .build();
like image 23
Yuri Schimke Avatar answered Oct 01 '22 04:10

Yuri Schimke