如何在okhttp中更改请求的超时

时间:2017-10-20 08:31:08

标签: okhttp3 okhttp

通常我们为okHttp客户端设置超时,我们使用该客户端的单个实例。因此,一旦生成该客户端,我们就无法更改该超时。

如何更改特定请求的超时?无论如何还有 没有创建新客户端吗?

一些呼叫通常需要花费更多时间至少每个应用程序1/2,这需要比其他呼叫更多的超时。如果请求可以覆盖默认超时,那就太好了。

3 个答案:

答案 0 :(得分:4)

答案 1 :(得分:4)

更新至翻新版2.5.0可以使用Invocation

  

新增:调用类提供对调用的方法和参数列表的引用,作为基础OkHttp调用上的标记。可以从OkHttp拦截器访问它,以进行日志记录,分析或指标聚合之类的事情。

这样,您可以创建一个SpecificTimeout批注,仅在需要设置不同超时时间的请求上使用,并在OkHttp Interceptor上读取其值以更改此时的超时

自定义注释

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

服务界面

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

拦截器

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.value(), timeout.unit())
                       .withConnectTimeout(timeout.value(), timeout.unit())
                       .withWriteTimeout(timeout.value(), 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();

答案 2 :(得分:-1)

我认为一个好方法是读取拦截器上的自定义标头并将当前超时更改为包含此特定标头的调用,这比创建注释并使用反射来读取它更好。例:

class TimeoutInterceptor : Interceptor {

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

        return request.header("Custom-Timeout")?.let {
            val newTimeout = it.toInt()
            chain.withReadTimeout(newTimeout, TimeUnit.MILLISECONDS)
                .withConnectTimeout(newTimeout, TimeUnit.MILLISECONDS)
                .withWriteTimeout(newTimeout, TimeUnit.MILLISECONDS)
                .proceed(request)
        } ?: chain.proceed(request)
    }
}