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成员–>获取超时属性,这种修改却不行,不知道为啥?知道原因的还请在评论里告知

posted @ 2018-04-13 17:52  帅气好男人_jack  阅读(123)  评论(0编辑  收藏  举报  来源