美文网首页
Retrofit 拾遗

Retrofit 拾遗

作者: spiritTalk | 来源:发表于2017-10-20 08:55 被阅读25次
    (一)是否可以自定义 HttpClient?

    Retrofit 的静态内部类 Builder 的 client(OkHttpClient client) 方法接收 OkHttpClient 参数,但其 callFactory(okhttp3.Call.Factory factory) 方法接收 okhttp3.Call.Factory 参数,那么也就可以自定义 HttpClient,只要实现 okhttp3.Call.Factory 的 Call newCall(Request request) 就行了呗。

        public Builder client(OkHttpClient client) {
          return callFactory(checkNotNull(client, "client == null"));
        }
    
        public Builder callFactory(okhttp3.Call.Factory factory) {
          this.callFactory = checkNotNull(factory, "factory == null");
          return this;
        }
    
    (二)预加载

    我们知道 Retrofit 通过注解来解释我们定义的接口方法,其中用到动态代理、反射以及解析的流程势必会耗费时间,具体可以在自己项目中输出 log 看下 create() 方法的耗时。

    通常 app 在启动到首页的过程会请求多个接口,配置相关、检测升级、拉取首页数据等等,这种情况下可能会执行一大堆 loadServiceMethod() 方法,会带来性能、速度方面的影响。这个时候我们就可以设置 validateEagerly 为 true 进行预加载,提前把将要用到的 serviceMethod 加载到内存里。

      public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);
        // 判断是否需要预加载
        if (validateEagerly) {
          eagerlyValidateMethods(service);
        }
        // 返回一个动态代理的类对象
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              // 代理对象调用接口方法时,便会调用该 invoke() 方法
              @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                // 此处也是通过 loadServiceMethod 方法来返回 serviceMethod
                ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                // 封装了 OkHttpCall 实例来请求网络,通常对应 OkHttp
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                // 处理接口方法的返回类型 
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    
      private void eagerlyValidateMethods(Class<?> service) {
        Platform platform = Platform.get();
        // 遍历接口中的所有方法
        for (Method method : service.getDeclaredMethods()) {
          if (!platform.isDefaultMethod(method)) {
            loadServiceMethod(method);
          }
        }
      }
    
      ServiceMethod<?, ?> loadServiceMethod(Method method) {
        // 先从缓存中读取,如果有则返回
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;
        // 缓存中没有,则构建新的并放入缓存
        synchronized (serviceMethodCache) {
          result = serviceMethodCache.get(method);
          if (result == null) {
            result = new ServiceMethod.Builder<>(this, method).build();
            serviceMethodCache.put(method, result);
          }
        }
        return result;
      }
    

    关于动态代理可以参考:代理模式及Java实现动态代理

    相关文章

      网友评论

          本文标题:Retrofit 拾遗

          本文链接:https://www.haomeiwen.com/subject/hlvsuxtx.html