Retrofit源码分析
Retrofit源码分析
街角的小丑 发表于3个月前
Retrofit源码分析
  • 发表于 3个月前
  • 阅读 5
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

前言

    第一次接触retrofit的时候还是个菜鸟(现在也是),使用一套规则定义一个接口,没有实现,结果竟然能够顺利完成和okhttp的对接。于是想要了解一下它的实现原理。

    本文仅是简单的源码分析,在读本文之前,或许应该先读一下下面这篇文章:

https://my.oschina.net/zzxzzg/blog/993685

Retrofit.Build

    Retrofit总是从一个Build开始,我们会在这个build中进行一些全局性的设置,比如baseUrl,Converter,CallAdapter,okhttpclient等。

    所以Retrofit.Build.build()功能并不复杂,保存设置的项目,创建一个真正 的Retrofit对象,不过其实还是有一些值得注意的

  1.     设置了一个默认的callbackExecutor(方法回调的线程执行器),就会使用默认的,而在Android平台中,默认就是主线程中执行,通过一个叫做MainThreadExecutor的类。
  2. 无论是否添加了自己的CallAdapter,都会添加一个默认的CallAdapter,而在android中,就是类ExecutorCallAdapterFactory.

    注:    CallAdapter 就是将返回的Call类型进行封装的一个适配器,Converter是对返回的ResponseBody进行封装处理的适配器。

Retrofit.create

    Retrofit所有神奇的起源,我们通过调用该方法,将一个接口变成了一个可以调用的类。

    实际上使用的原理就是Proxy代理:

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

    首先是eagerlyValidateMethods方法,将service中的所有方法封装成一个ServiceMethod对象,并存储起来。至于ServiceMethod是什么,接下去再看。

    然后就返回了一个ProxyInstance,当我们调用定义的接口中的方法时,就会转而调用invoke方法。

    invoke方法的工作其实就是删选出该方法是否是接口中定义的,如果是,那么获取该方法的servicemethod,然后创建一个okhttpcall(请求结果回调)。最后再将okhttpcall用适当的calladapter(见上)进行封装后返回。

ExecutorCallAdapterFactory     ExecutorCallbackCall

    CallAdapter.Factory 声明了一个get的接口,就是根据返回类型和注解(你在接口中声明的某个方法的返回类型,和方法的注解)生产一个CallAdapter(每个方法都会生成一个CallAdapter).

    而CallAdapter实际上之前有说过,就是将源返回值(Call<?>)进行封装的一个适配器类,通过调用方法adapt进行封装。

    知道这两个后,那么久看下Androir默认一定会提供的ExecutorCallAdapterFactory,这个东西的get方法很简单,只要返回类型是Call的,都匹配,并返回一个CallAdapter。这个CallAdapter的adapt方法返回一个ExecutorCallbackCall类型对象,继承与call,它的作用非常简单直接,将所有call中的回调方法迁移到指定的线程。(而Android中默认指定了主线程。)

OKHttpCall

    对于okhttp的使用这里我们不做介绍,我们知道okhttp总是会有大概如下的调用

    Call call = client.newCall(request);

    call.enqueue(CallBack ...)

    call.execute

    通过request产生一个call,然后在该call上进行同步或者异步的请求。而retrofit的okhttpcall也是采用同样的接口。

    我们在retrofit.create中已经介绍了,我们通过一个servicemethod和对应的参数来生成一个okhttpcall,然后将这个call在传给对应的calldapter进行一次封装,等待触发enqueue或者execute(不同的calladapter封装成不同的类型,rxjava2calladapter或者之前的ExecutorCallbackCall等,触发方式不同,但是本质上就是调用call的这两个方法。)    

    我们已enqueue为例(execute其实一样),首先通过调用createRawCall方法来生成一个call。

 private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

    很简单,调用serviceMethod中的 toRequest方法生成request,然后调用callFactory的newCall(callFactory就是我们设置的okhttpclient或者默认的new OkhttpClient)。

    生成call以后,就通过在这个call上调用enqueue进行请求,并且注册回调。回调的onResponse方法中,我们会对response进行一次解析,通过方法parseResponse。该方法实现有些复杂,但是功能很清晰,就是将okhttp的response包装成retrofit自己提供的Response对象(converter的body解析也是在这里进行调用的,具体就是调用了serviceMethod的toResponse的方法)。

ServiceMethod

   同上上述分析,我们发现ServiceMethod承载的最主要的功能就是toRequest方法,生成一个request(当然也有toResponse来进行解析,但是其实代码很简单)。

   如果你觉得我会详细去分析这个东西,那么你就错了,不妨亲自打开代码,看看build方法和toRequest方法在干嘛。其中已经并不涉及到架构问题,虽然不一定简单,甚至说是复杂,但是至少我们知道它做的就是通过解析我们定义时使用的注解,将他和传入的参数进行合并,生成request的过程。

总结

    retrofit代码的原理并不复杂,但是在笔者看来,算得上是adapter界的楷模,在适配器的使用上非常规范标准,值得借鉴。 

共有 人打赏支持
粉丝 0
博文 57
码字总数 94033
×
街角的小丑
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: