retrfoit+okhttp動態改變連線超時時間
阿新 • • 發佈:2019-01-01
設定連線超時時間的基本用法
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成員–>獲取超時屬性,這種修改卻不行,不知道為啥?知道原因的還請在評論裡告知