retrfoit+okhttp动态改变连接超时时间
设置连接超时时间的基本用法
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(25, TimeUnit.SECONDS);
builder.connectTimeout(25, TimeUnit.SECONDS).build();
Retrofit retrofit =
new Retrofit.Builder().baseUrl(IotApiService.ENDPOINT)
.client(client).build();
retrofit.create(IotApiService.class);
一般重新修改超时的方法
1. 重新创建一个OkHttpClient,修改里面的超时时间
2. retrofit替换这个新的client
3. 最后,在create的一个新的网络接口对象实例
这种修改方法是生成一个新的网络接口访问实例,替换掉旧的,从而达到了修改超时时间条件
但是,如果retrofit.create创建的IotApiService实例不能变呢?例如使用dagger框架的情况下,一开始就将IotApiService依赖注入到每个需要它的对象中,这种情况上诉的修改方法就行不通了
so what should i do ?
先说怎么做,在分析原因:
我们保存好OkHttpClient这个实例,通过反射获取这个实例内部关于超时的参数,在设置回去即可:
/**
* 修改client超时时间
* @param ConnectTime
*/
public static void modify(int ConnectTime){
if(client == null){
return;
}
try {
Field connectTimeoutField = client.getClass().getDeclaredField("connectTimeout");
connectTimeoutField.setAccessible(true);
connectTimeoutField.setInt(client, ConnectTime);
Field readTimeout = client.getClass().getDeclaredField("readTimeout");
readTimeout.setAccessible(true);
readTimeout.setInt(client, ConnectTime);
Field writeTimeout = client.getClass().getDeclaredField("writeTimeout");
writeTimeout.setAccessible(true);
writeTimeout.setInt(client, ConnectTime);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
问题来了,为什么了修改了client,我们的网络接口IotApiService就变了呢?
这就得分析源码,查看client、Retrofit以及创建的网络接口之间的关系了
OkHttpClient的超时时间
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(25, TimeUnit.SECONDS);
builder.connectTimeout(25, TimeUnit.SECONDS).build();
查看源码,上诉这种建造中模式构建client,最终都是改变了OkHttpClient的这几个成员:
final int connectTimeout;
final int readTimeout;
final int writeTimeout;
/**
* Sets the default connect timeout for new connections. A value of 0 means no timeout,
* otherwise values must be between 1 and {@link Integer#MAX_VALUE} when converted to
* milliseconds.
*/
public Builder connectTimeout(long timeout, TimeUnit unit) {
if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
if (unit == null) throw new NullPointerException("unit == null");
long millis = unit.toMillis(timeout);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
connectTimeout = (int) millis; //这里设置的,注意时间单位是ms
return this;
}
Retrofit和OKHttpClient关系?
源码new Retrofit.Builder()..client(client)…
//1
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
//2
static <T> T checkNotNull(T object, String message) {
if (object == null) {
throw new NullPointerException(message);
}
return object;
}
//3
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
上诉的代码实质就是获取okhttpclient的一个引用,并没有重新创建新的值,而最后retrofit.create是一个动态代理行为,起最终超时都是来自一开始的okhttpclient的那个实例对象,并没有创建新对象,所以修改最初的okhttpclient就可以了。
有一个问题:我试着反射去修改Retrfit->okhttpclient成员–>获取超时属性,这种修改却不行,不知道为啥?知道原因的还请在评论里告知