通常我们为okHttp客户端设置超时,我们使用该客户端的单个实例.因此,一旦生成该客户端,我们就无法更改该超时.
如何更改特定请求的超时?反正有没有创建新客户端吗?
一些呼叫需要花费更多时间至少每个应用程序1/2,这需要比其他呼叫更多的超时.如果请求可以覆盖默认超时,那将是很好的.
在 3.9 中,可以在拦截器中设置每个请求
@Test public void chainWithReadTimeout() throws Exception {
Interceptor interceptor1 = new Interceptor() {
@Override public Response intercept(Chain chainA) throws IOException {
assertEquals(5000, chainA.readTimeoutMillis());
Chain chainB = chainA.withReadTimeout(100, TimeUnit.MILLISECONDS);
assertEquals(100, chainB.readTimeoutMillis());
return chainB.proceed(chainA.request());
}
};
}
Run Code Online (Sandbox Code Playgroud)
请参阅https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PerCallSettings.java,它会创建仅修改某些设置的浅克隆.
// Copy to customize OkHttp for this request.
OkHttpClient client2 = client.newBuilder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
Run Code Online (Sandbox Code Playgroud)
更新到Retrofit 2.5.0可以使用Invocationclass
新增:调用类提供对调用的方法和参数列表的引用,作为基础OkHttp调用上的标记。可以从OkHttp拦截器访问它,以进行日志记录,分析或指标聚合之类的操作。
这样,您可以创建SpecificTimeout仅在需要设置不同超时时间的请求上使用的注释,并在上读取其值OkHttp Interceptor以更改该时间的超时。
自定义注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SpecificTimeout {
int duration();
TimeUnit unit();
}
Run Code Online (Sandbox Code Playgroud)
服务介面
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();
}
Run Code Online (Sandbox Code Playgroud)
拦截器
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);
}
}
Run Code Online (Sandbox Code Playgroud)
OkHttp构建器
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();
Run Code Online (Sandbox Code Playgroud)