Retrofit2源码的阅读

前几篇笔记记录的都是Retrofit2的使用,但是它内部到底干了什么我们还是啥都不知道。这让我们在使用Retrofit时,心里没底。所以这次我们就来简单过一遍retrofit的源码。

看Retrofit的源码对于毫无经验的我来说,第一步应该从哪呢?我决定从这开始:

 retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client.build())
                .addConverterFactory(GsonConverterFactory.create())              
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        apiService = retrofit.create(MovieService.class);

接下来我们要干什么,很自然的我们点进Builder()看看这里干了什么:

一、.Builder()
public Builder() {
      this(Platform.get());
}

对,是的我们没有看错,就这么点东西。这么点东西我们也看到了两部分东西,一个是Platform.get(),另一个是this(…)。

  • Platform.get()干了什么呢?继续跟进源码(不贴代码了,可以自己看一下)可以发现,这只是获取了设备平台信息;
  • this()的用在这里相信大家都知道是什么意思,调用了一个重载的方法。
Builder(Platform platform) {
      this.platform = platform;
      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
    }

看到这里我们就明白了,Builder()干了两件事:

  1. 创建了Platform,获取了设备平台信息;
  2. 添加了一个内部转换器工厂,可以看出来converterFactories是一个集合,而事实也是这样的。
private List<Converter.Factory> converterFactories = new ArrayList<>();
二、.baseUrl(url)

接着在看看这里的代码

public Builder baseUrl(String baseUrl) {
      //baseUrl非空验证
      checkNotNull(baseUrl, "baseUrl == null");
      //创建HttpUrl对象 
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }

可以看到首先给我们的baseUrl来了个验证,如果是null的话我们会来一个NullPointerException;
然后,就是创建了一个HttpUrl对象,在这里会判断是否是http或https的URL,如果不是就返回null。

三、addConverterFactory()、addCallAdapterFactory

这两个干的事情类似

/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
}

/**
* Add a call adapter factory for supporting service method returntypes other than {@link Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
}

分别添加转换器工厂和适配器工厂,而且这两个都是集合,因此很显然的转换器工厂和适配器工厂都是可以添加多个的。

四、.client()

创建client对象,

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;
}
五、.build()创建Retrofit对象
public Retrofit build() {
    if (baseUrl == null) {
      throw new IllegalStateException("Base URL required.");
    }

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
      callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
      callbackExecutor = platform.defaultCallbackExecutor();
    }

    List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
    adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

    return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
        callbackExecutor, validateEagerly);
}

初始化了必要的对象;

六、.create(xx.class)

xx.class是我们的接口类,我们看看源码里干了什么

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();

          @Override public Object invoke(Object proxy, Method method, 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);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

我们看到Utils.validateServiceInterface(service);对我们传入的service进行了检验(service是我们写的接口类);
- 检查了我们的service是否是interface类型;
- 检查了我们的service内部的请求接口数量是否大于0。

validateEagerly:是否提前执行了方法参数的注解解析。

接下来我们看到了Proxy.newProxyInstance熟悉的同学,一下就看出来这是个动态代理;简单来说,当我们调用接口发起请求时,会走invoke里的代码;

我么在看看重写的invoke方法做了哪些操作。

ServiceMethod serviceMethod = loadServiceMethod(method);

在 这里创建了一个ServiceMethod实例对象;在loadServiceMethod(method)中创建了这个对象,传入Method method,这个method即我们请求接口的方法名。

ServiceMethod loadServiceMethod(Method method) {
   ServiceMethod result;
   synchronized (serviceMethodCache) {
     //从集合中根据方法名 获取对应的ServiceMethod对象
     result = serviceMethodCache.get(method);
     //如果集合中没有方法  创建ServiceMethod对象 然后存放到集合中
     if (result == null) {
       result = new ServiceMethod.Builder(this, method).build();
       serviceMethodCache.put(method, result);
     }
   }
   return result;
 }

serviceMethodCache是一个集合,存放了请求的method信息;

private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();

如果在集合中没有对应的该ServiceMethod对象,我们就创建一个;

public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //获取接口方法的注解
      this.methodAnnotations = method.getAnnotations();
      //获取参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      //获取参数注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

创建OkHttpCall对象

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
  • serviceMethod:请求接口方法的信息;
  • args:请求参数。
serviceMethod.callAdapter.adapt(okHttpCall);

调用了XXCallAdapter的方法adapt(),适配器工厂;在适配器工厂里进行了类型转换。见前篇Retrofit2.0的使用之自定义CallAdapter.Factory。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值