android中Retrofit2源码解析(新版本)

android中Retrofit源码解析(新版)

在android开发中我们原生应用发起网络请求的时候,不免需要使用android对网络请求的封装,它提供了对http协议底层的抽象,我们可以通过它提供的方法直接调用http请求。在android2.2版本及其以前的版本使用HttpClient,在android2.3版本及其之后我们使用了httpUrlConnection,而且在6.0之后android移除了httpClient,我们在高版本的API中只能使用HttpUrlConnection了。

1.1 retrofit和OkHttp的关系

但是实际情况是使用了httpUrlConnection还是很繁琐,我们还是要去考虑超时时间,服务器异常情况、数据流转为实体对象这些烦恼。所以有了对android内置的HttpUrlConnection or httpClient的包装,让我们专心处理业务逻辑。oKHttp就诞生了,android4.4版本以后都内置了oKHttp了,而我们要讨论的retrofit就是再次对okHttp的包装,丰富了很多强大的功能,比如能和Rxjava这个流行的框架结合,返回结果能回调到UI线程等。oKHttp的源码涉及到了对阻塞队列,线程池的应用,我们下一节进行探讨。

1.2 retrofit的本质

retrofit的本质就是应用了大量的设计模式对Okhttp进行了封装,加入了网络数据转换、网络请求回调、网络请求适配这几个主要的功能。它本身肯定不会去发请求的,发请求交给了OkHttp,它只对调用方式和返回结果进行处理其他的不关它的事。为什么要去研究retrofit的源码呢?因为它封装的方式解耦性很高,功能调用十分简洁,可以参照它对我们的代码也能进行改造。

1.3 源码解析(retrofit:2.4.0)

1.3.1 retrofit的创建

一起打开IDE阅读源码更虚浮!retrofit的创建是整个框架的入口,它肯定会提前准备好很多看不懂的变量进行初始化,但是这不能阻挡我们,往后看就能理解它代表的含义了。根据官方的文档,retrofit的创建使用了建造者模式。

Retrofit retrofit = new Retrofit.Builder() 
//基本URL
.baseUrl("https://www.baidu.com") 
//网络请求适配器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
//网络请求数据转换器
.addConverterFactory(GsonConverterFactory.create()) 
//网络请求执行器
.client(new OkHttpClient())       
.build(); 

所谓建造者模式就是有builder关键字的方式,就是这么简单!当然这是一个玩喜,建造者模式和我们以前 get/set 类的属性没有什么本质的区别,主要是将这些set方法全部提取出来 形成一个抽象类或者内部类,然后在一个建造者类里面去设置属性,返回一个实体类对象,列如:

public abstract Builder{
public void BulidProperty(String url);
}
public class RealBuilder extends Builder{
private RealObject object;
public void BulidProperty(String url){
    object.SetProperty(url);
     }
 public RealObject build(){
     return RealObject;
     }
}

简单的思想大概是这样的,具体的我们可以看一下Retrofit中的源码。第一行代码

//第一行代码
Retrofit retrofit = new Retrofit.Builder() 

很明显这个Builder是一个Retrofit的内部类,那说明建造者不是继承了抽象类,而是使用了内部类来设置属性。来看一下这个内部类,如下:


public static final class Builder { 
    //不知道这是什么东东先放在一边
    private final Platform platform;
    //很明显出现了okhttp,就知道它肯定负责去发请求
    private okhttp3.Call.Factory callFactory;  
    // 8必多说 大家都懂
    private HttpUrl baseUrl;
    //很明显它是存数据转换用的,但是为什么搞一个list 懵b?
    private final List converterFactories = new ArrayList<>(); 
    //很明显它存网络适配器用的,再次疑问这个网络适配器是什么东东?
    private final List adapterFactories = new ArrayList<>(); 
    //很明显他是一个回调执行器,这个有什么用呢?
    private Executor callbackExecutor; 
    //这肯定是校验Flag目前不知道有什么用
    private boolean validateEagerly;

里面看不懂的变量主要有adapterFactories存的网络适配器工厂(CallAdapter.Factory),很明显他后面会使用工厂设计模式去产生CallAdapter的对象,至于数据转换器(converter)我们都知道http请求返回来的是数据流InputStream方式的,转为Json,XML之类需要一个转换器,类似于一个double转int的工具类。

  • 网络适配器的含义及其作用:网络适配器是我自己给他的定义,从命名上来看是叫:CallAdapter,Call肯定是来发请求的,Adapter忆往昔峥嵘岁月,在listView里面是界面和数据的桥梁,同理这里的CallAdapter应该是客户端和网络之间桥梁。客户端发请求的操作肯定是要通过它的。如图:
android中Retrofit2源码解析(新版本)_第1张图片
image.png

这样我们就可以清楚的看到了CallAdapter的作用了,它对OkHttp进行包装,我们调用请求方法的时候都要通过它。它同时持有了okHttp对象和回调执行器的对象,这样它通过Okhttp拿到数据之后,用回调执行器回调。

  • 回调执行器:回调执行器就是在拿到数据结果之后,我们怎么返回结果的问题,主要的问题就是由于是异步请求,我们想要使用数据填充界面,需要切换到主线程。
  //再看看构造函数
  Retrofit retrofit = new Retrofit.Builder() 

这个内部类的构造函数做了些什么内容?就一句调用自己的有参构造函数,佛了!

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

我们来看看这个有参构造函数和Platform类是什么东东:

    //Platform类
class Platform {
  private static final Platform PLATFORM = findPlatform();
  static Platform get() {
  //f返回一个实例就完事了
    return PLATFORM;
  }
  //根据不同运行平台返回对应的Platforem对象 
     private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

看到这里我们就明白了,他根据运行的平台不同来返回相应的对象,我们这里只分析 new Adnroid();看看里面有什么内容:

static class Android extends Platform {
 //一个默认的回调执行器
    @Override
     public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    //很明显 很熟悉 !创建了一个默认的CallAdapter(网络适配器),而且传入了一个回调执行器(回调执行器可以自定义,不然就是用默认绑定主线程)
    @Override 
    CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
     static class MainThreadExecutor implements Executor {
     //给力 绑定了主线程的 looper (关于Handler的详细内容可以自己查询)
      private final Handler handler = new Handler(Looper.getMainLooper());
      @Override 
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

到此我们明白了 Platfrom的作用了,它提供了一个默认的CallAdapter.Factory用来生产CallAdapter,还提供了一个绑定主线程的默认回调执行器。

再次回头看创建Retrofit的其他代码

Retrofit retrofit = new Retrofit.Builder() 
//基本URL
.baseUrl("https://www.baidu.com")
//可以自定义回调执行器,否则默认回调到主线程
.callbackExecutor("xxxx")
//网络请求适配器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
//网络请求数据转换器
.addConverterFactory(GsonConverterFactory.create()) 
//网络请求执行器
.client(new OkHttpClient())       
.build(); 

baseUrl、add这些方法是给内部类属性赋值,我们主要来看build()方法。

 public Retrofit build() {
    //可见baseUrl 是必须的 使用的时候要注意
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //很明显 生产网络请求的工厂,如果你不传入自定义的okHttp对象,他会默认使用okHttpclient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //如果没有自定义,加入刚刚说过的默认调到到主线程
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      //将传入到内部类callAdapter copy一份 传入到retrofit的构造函数
      List adapterFactories = new ArrayList<>(this.adapterFactories);
        //它会添加一个默认的网络适配器,这个网络适配器它持有callbackExecutor回调执行器的对象。
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
      //很明显类似adapterFactories 添加了一个默认,再copy一份到 retrofit的构造函数中。
      List converterFactories =new ArrayList<>(1 + this.converterFactories.size());
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      //返回retrofit的实例对象就完事了
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
  }

这里的代码都很简单,但是有几个疑问?为什么这个adapterFactories和converterFactories都是list呢,它里面都存了些什么。

  • adapterFactories: 一个list集合,存储了网络适配器工厂,根据上面的代码我们可以看到它里面的内容是:先添加了自定义的、后面添加了一个默认的,总共两个元素。在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory。其他的没有用过,但是看到Rxjava我们就知道了,如果想要和Rxjava结合起来这个RxJavaCallAdapterFactory必须添加进去
//通过这个添加进去,是不是可以添加多个呢?
Retrofit retrofit = new Retrofit.Builder() 
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//我们还可以添加
// adapterFactories里面顺序
// 自定义1-自定义2-.....默认。
addCallAdapterFactory(Java8CallAdapterFactory.create())
addCallAdapterFactory(GuavaCallAdapterFactory.create())
//converter 同理啊铁子!
.addConverterFactory(GsonConverterFactory.create()) 

也不会有问题,因为我们网络请求都是多种多样的,上面已经说得我们发请求就是操作CallAdapter,所以有结果返回的时候也需要通过CallAdapter。有时候我们需要Rxjava的observeable这种返回对象,有时候我们还是需要Call这种类型的返回对象,所以他需要一个list去组装对应的CalladapterFactory,Call代表了默认CallAapter返回出来的的,Observable代表了我们添加进去的RxJavaCallAdapter返回出来的。同理我们需要从CallAdapter得到想要的数据类型,converterFactories也需要多个。

    @GET
    //我想要Observable 需要相应的的CallAdapter
   Observable download(@Url String url);
    @GET
        //我想要Call 默认的CallAdapter就行
        //同时还需要将结果变成IModel 怎么说吧你
    Calldownload(@Url String url);

总结:我们清楚的看到了,retrofit的创建过程,主要的内容就是四个器的初始化,网络适配器(CallAdapter),数据转换器(conver),请求执行器(oKHttp),回调执行器(callbackExecutor)。关注点在我们发请求操作都是CallAdapter,它肯定持有其他三个的引用,就像吃鸡里面他是我们的角色,其他的是M4,头盔 药品等。

1.3.2 创建网络请求接口的实例。

对我们的的注解定义的接口方法进行解析,从而创建实例,有点迷惑?什么实例,干什么用的?我们继续往下看。

retrofit.create(RetrofitService.class);

看到这种传入.class的 ,我们可以想到肯定会用到反射。

 public  T create(final Class service) {
    //校验接口正确性,是否符合注解规则
    Utils.validateServiceInterface(service);
    //validateEagerly 这个变量主要是作用是 是否提前加入缓存
    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 {
              //如果是java里面的基类不做处理 
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // 这个没什么用android平台默认返回的是false的
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
           //非常重要的3行代码
           //解析方法的返回参数 请求参数 请求类型等
            ServiceMethod serviceMethod =(ServiceMethod) loadServiceMethod(method);
            //很明显OkHttp就知道他是一个网络执行器
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明显他 肯定是调用了callAdapter  
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }
 
 

这里的代码稍微有一丢丢复杂,主要理解代理模式。代理代理,不知道大家是否知道代购。比如你想买一件surpene的衣服,当然superme肯定买不起,只能买买faker。又拉下不脸,找了一个代购。

android中Retrofit2源码解析(新版本)_第2张图片
image.png

代理类会获取被代理类的所有方法,并返回一个被代理类的对象,这个对象就是虚拟的你,通过它去购买需要的商品。Proxy.newProxyInstance(xxx)是固定用法,只要传入xxx.class参数就行。

     //固定格式
     ClassLoader classLoader =Shop.class.getClassLoader();
     //固定格式,三个参数,传入Shop.class参数,获取所有方法,返回代理对象。
     Shop shopProy = (Shop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //回调原来类的方法,该怎么做就怎么做
                Object result = method.invoke(proxy,args);
                //也可以自己实现 不回调原来的方法。
                //.............................
                return result;
            }
        });

这里的Invoke方法,就是代理方法的实现,method.invoke()代表了回调原来的方法,这里也可以自己去实现方法,只要返回对应的类型。代理模式优点就是提供了一个拦截接口,不管你什么方法调用都会先进入Invoke。具体内容可以学习JAVA反射来加深印象。

  .........................................
  //validateEagerly 这个变量主要是作用是 是否提前加入缓存
   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 {
              //.............................
           //非常重要的3行代码
           //解析方法的返回参数 请求参数 请求类型等 关键代码1
            ServiceMethod serviceMethod =(ServiceMethod) loadServiceMethod(method);
            //很明显OkHttp就知道他是一个网络执行器 关键代码2
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明显他 肯定是调用了callAdapter   关键代码3
            return serviceMethod.adapt(okHttpCall);
            }
 
 

回到代理创建接口实例的方法中,我们创建接口的时候都是只写了方法名,没有具体的实现,所以在代理对象并不能回调,它只能自己去实现而且还要返回你要想的结果类型。苦b啊!

public interface RetrofitService {
  //没有方法体 只有名字 怎么破(只能靠retrofit给我们实行)
   @GET
  Observable download(@Url String url);
   // 没有方法体,只有名字 怎么破
   @GET
   Calldownload(@Url String url);
}

在retrofi中,利用了ServceMehod这个类来进行实现方法体,它会获取到接口方法的参数,返回值类型,请求方式等所有参数。看一下关键代码1,loadServiceMethod()!!

 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();//我只是一个建造者,传入了retrofit的对象,拥有了adapterFactorese等所有属性。
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

代码很简单,对调用的方法做一个缓存,第一次调用的时候才会去解析方法,其他情况下会使用缓存。同时我们也应该知道validateEagerly这个Flag的作用了,如果你设置为true会创建动态代理对象的时候将所有的方法解析缓存,否则就只会在第一次调用的时候去缓存。
虽然已经知道了ServiceMethod会对我们请求的方法进行一顿瞎x操作,各种解析分析组装,但是我们还要要去看看实况,它采用了建造者模式(builder),直接看.build()方法。

 public ServiceMethod build() {
     ..........................................//
     //根据返回值类型,在adapterFactories的list里面去寻找CallAdapter,如observeable,就会寻找RxjavCallAdapter.Factory 工厂模式产生CallAdapter 的对象。
      callAdapter = createCallAdapter();
      //获取返回值中的数据类型
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      //根据CallAdapter的返回的值中的数据类型(如: Call download(), 就会根据 ‘ Bean’去寻找Gson转换器)去遍历converterList找转换器,Converter 的对象。
      responseConverter = createResponseConverter();
      //遍历方法中的所有注解 一顿操作保存起来。
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      int parameterCount = parameterAnnotationsArray.length;
      // 保存请求参数的工具类
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        ..................///
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        ..................//
        //遍历方法参数中的所有注解和变量到parameterHandlers
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      .......................//
      //返回一个 ServiceMethod的实例
      return new ServiceMethod<>(this);
    }

主要作用是根据方法的返回值类型,获取相应的网络适配器、数据转换器以及拆卸参数类型等保存在parameterHandlers中。列如:createCallAdapter会去遍历callAdapterFactories找到相应的callAdapter。

public CallAdapter nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
      //.......................................................
      //根据返回值遍历callAdapterFactories
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
     // get返回了一个CallAdapter对象
      CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    
    //这里假设我们返回值是 Call 类型的 ,默认的ExecutorCallAdapterFactory会被匹配到。看看它的get方法
  @Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    //给力呀 铁子 返回了一个 CallAdapter对象
    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }
      // 我就是方法体啊铁子 
      @Override public Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
 
 

其中Calladapter中的adapt方法就是方法体了。后续详细介绍这个CallAdapter类。
根据关键代码1, loadServiceMethod()返回了一个ServiceMethod的实例,它里面包含了你调用方法的所有信息,包含注解,参数类型,参数名,返回值类型等,来看看它里面主要的属性:

  final class ServiceMethod {
   .............................//
  //这个是Okhttp的工厂实例,用来生产请求call的
  private final okhttp3.Call.Factory callFactory;
  //桥梁callAdapter 实例 发请求都是它在操作okhttp
  private final CallAdapter callAdapter;
  // 8 必再说
  private final HttpUrl baseUrl;
  //数据转换器实例
  private final Converter responseConverter;
.......................//
//存储请求参数的集合
  private final ParameterHandler[] parameterHandlers;

到此Retrofi已经实现了高度的解耦,定义一个请求方法,我只想调用一下得到结果,至于怎么请求的,和怎么转换结果都不想关注。retrofit在这里使用了外观模式,只用定义方法入口(Retrofit.create(YourInterface.Class)),减少了对内部细节的依赖,里面发生了变化,我们也不用担心。
继续看关键代码2:

//很明显这里使用了动态代理模式
    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 {
              //.............................
           //非常重要的3行代码
           //解析方法的返回参数 请求参数 请求类型等 关键代码1
            ServiceMethod serviceMethod =(ServiceMethod) loadServiceMethod(method);
            //很明显OkHttp就知道他是一个网络执行器 关键代码2
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //很明显他 肯定是调用了callAdapter   关键代码3
            return serviceMethod.adapt(okHttpCall);
            }
 
 

将servcieMethod传入到oKhttpCall,serviceMethod已经把请求参数拆卸下来存储在了parameterHandlers中,OkHttpCall会取出参数类型和值进行组装请求。

final class OkHttpCall implements Call {
  private final ServiceMethod serviceMethod;//含有所有网络请求参数类型等等
  private final @Nullable Object[] args;//请求参数的值

  private volatile boolean canceled;//取消请求Falg

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;//真正发请求的Okhttp
............................................//

  }

OkHttpCall里面有了okhttp对象,使用它来进行发请求操作,具体我们往下看。
关键代码3:

        //很明显他 肯定是调用了callAdapter   关键代码3
            return serviceMethod.adapt(okHttpCall);
    // 在ServiceMethod中adapt 调用了callAdapter
    final class ServiceMethod {
    ..................................//
      T adapt(Call call) {
          return callAdapter.adapt(call);
        }
   ...............................//     
     }      

将生产好的Call对象传入到adapter中,然后开始实现方法体.
这里结合实例来看:

    //我想要Call类型的返回值,使用默认CallAdapter的就行了
    @GET
    Calldownload(@Url String url);
    
    //使用 mRetrofitService.downloadADfile(xxx),就是在调用  serviceMethod.adapt(okHttpCall);
    Call call = mRetrofitService.downloadADfile("www.kawayi.com");   

我们在这里的 "call = "返回的是什么呢?来看一哈肯定很简单。

//根据刚返回类型'Call' 遍历CallAdapterFactories循环出得到默认CallAdapter
public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }
      //返回了一个ExecutorCallbackCall对象 来看一哈
      @Override public Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
 
 

很显然返回了一个ExecutorCallbackCall对象,ExecutorCallbackCall内容并不是很复杂。

//这里是ExecutorCallbackCall 继承了Call
static final class ExecutorCallbackCall implements Call {
  //回调执行器,有自定义就用自定义否则就会使用platform这个对象生产出绑定主线程的回调
  final Executor callbackExecutor;
  //这里传入的是OkhttpCall
  final Call delegate;
  //构造函数,传入了OkhttpCall,和回调执行器,装饰模式安排安排
  ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
  }
  //执行异步请求
  @Override public void enqueue(final Callback callback) {
    checkNotNull(callback, "callback == null");
    delegate.enqueue(new Callback() {
      @Override public void onResponse(Call call, final Response response) {
          //回调执行器 切换线程
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }
     .......................//
}

代码很简单,显然CallAdapter的内部类ExecutorCallbackCall拥有okhttp和回调执行器,所有的一切操作都在是它在执行了。这里使用了装饰模式,加强了okhttCall。装饰模式:就是不改变类文件和使用继承的情况下,动态地扩展一个对象的功能,是一种代替继承的方案。


android中Retrofit2源码解析(新版本)_第3张图片
image.png

C和A都继承了B,但C里面有A的对象,所以他可以调用A的方法,而且能添加一些A中没有的功能。如:

  
  static final class ExecutorCallbackCall implements Call {
   ......................................//
    //ExeCutorCallbackCall和delegate都继承了Call,但ExeCutorCallbackCall有回调执行,取消请求这些功能,得到了加强。
    final Call delegate;

这里的delegate得到了加强,拥有了切换线程的功能。

总结:retrofit.create(RetrofitService.class),使用了动态代理创建RetrofitService对象,并且对它接口中的方法进行了实现,根据返回值的类型,寻找CallAdapter和converter并且拆卸请求参数,组装请求,最后返回了Call的对象。

1.3.3 返回值执行网络请求

根据实例来看源码:


//我想要Call类型的返回值,使用默认CallAdapter的就行了 
@GET Calldownload(@Url String url); 
//实际上就是在调用serviceMethod.adapt(okHttpCall); 
Call call = mRetrofitService.downloadADfile("www.kawayi.com");
//发一个异步请求。
 call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {

            }
            @Override
            public void onFailure(Call call, Throwable t) {
            }
   });

根据刚刚分析的代码可以知道,返回的call对象是ExecutorCallbackCall的实例,enque执行异步请求的,就会调用ExecutorCallbackCall的enque方法。

//这里是ExecutorCallbackCall 继承了Call
static final class ExecutorCallbackCall implements Call {
  //执行异步请求
  @Override public void enqueue(final Callback callback) {
    checkNotNull(callback, "callback == null");
    //okhttpCall去执行请求,奥给力。
    delegate.enqueue(new Callback() {
      @Override public void onResponse(Call call, final Response response) { 
      //这只是一个回调执行器,切换线程
        callbackExecutor.execute(new Runnable() {
          @Override public void run() {
            if (delegate.isCanceled()) {
              callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
            } else {
              callback.onResponse(ExecutorCallbackCall.this, response);
            }
          }
        });
      }
     .......................//
}

代码中可以看到,我们传入的okHttpCall(serviceMethod.adapt(okHttpCall))会调用okttp去执行请求,并且用回调执行器回调okhttp返回的数据数据。
下面来看看okHttp具体是怎么处理的

 final class OkHttpCall implements Call {
  private final ServiceMethod serviceMethod;//含有所有网络请求参数类型等等
  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;//真正发请求的Okhttp
............................................//
  //发一个异步请求。实际上是okhttp操作
 @Override public void enqueue(final Callback callback) {
    checkNotNull(callback, "callback == null");
    //okhttp的实例
    okhttp3.Call call;
    ..............................................\\
   call = rawCall = createRawCall() ;//拿到parameterHandlers的参数,组装一个请求   
   ...........................................\\
   //真正的发一个请求
  call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response response;
        try {
        //使用数据转换器,转换一下就完事了。
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
         try {
         //回到到对应的CallbackCall中,默认是ExecutorCallbackCall
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
        
        

OkhttpCall首先先对请求进行一个组装,然后赋值给一个okhttp.Call的对象。通过call对象去发起请求,中间有异常超时对应的处理,拿到正确的请求结果之后,解析数据,回调到对应的CallbackCall,默认是ExecutorCallbackCall,最后在ExecutorCallbackCall中使用回调执行器再次回调。

2.1 总结

1、Retrofit对oKHttp层层封装,利用动态代理模式,实现接口定义的方法。
2、根据返回值类型匹配对应的CallAdapter,converter,这里使用了策略模式。在对应的callAdapter中使用了装饰器模式并且返回了一个加强的Call对象。
3、利用返回的Call对象来发请求,利用内部包装的OkHttp对象,执行请求。结果返回之后,converter解析数据,经过层层回调,到最后回调执行器切换线程。

参考文献
[1]刘望舒.Android进阶之光

你可能感兴趣的:(android中Retrofit2源码解析(新版本))