Retrofit2.0源码解读

Retrofit简介

Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用户的需求对结果进行解析

在这里插入图片描述
在这里插入图片描述

与Okhttp的区别

在这里插入图片描述

Retrofit的使用流程:

  • 创建Retrofit实例.
  • 创建网络请求接口实例
  • 发送网络请求

具体过程解释如下:

  1. 通过解析 网络请求接口的注解 配置 网络请求参数
  2. 通过 动态代理 生成 网络请求对象
  3. 通过 网络请求适配器 将 网络请求对象 进行平台适配

平台包括:Android、Rxjava、Guava和java8

  1. 通过 网络请求执行器 发送网络请求

  2. 通过 数据转换器 解析服务器返回的数据

  3. 通过 回调执行器 切换线程(子线程 ->>主线程)

  4. 用户在主线程处理返回结果

下面我们分析Retrofit源码,从使用流程的三个步骤来分析:

创建Retrofit实例源码解析

Retrofit类

<-- Retrofit-->
 public final class Retrofit {
  
  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
  // 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
  // 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等
  
  private final HttpUrl baseUrl;
  // 网络请求的url地址

  private final okhttp3.Call.Factory callFactory;
  // 网络请求器的工厂
  // 作用:生产网络请求器(Call)
  // Retrofit是默认使用okhttp
  
   private final List<CallAdapter.Factory> adapterFactories;
  // 网络请求适配器工厂的集合
  // 作用:放置网络请求适配器工厂
  // 网络请求适配器工厂作用:生产网络请求适配器(CallAdapter)
  // 下面会详细说明


  private final List<Converter.Factory> converterFactories;
  // 数据转换器工厂的集合
  // 作用:放置数据转换器工厂
  // 数据转换器工厂作用:生产数据转换器(converter)

  private final Executor callbackExecutor;
  // 回调方法执行器

private final boolean validateEagerly; 
// 标志位
// 作用:是否提前对业务接口中的注解进行验证转换的标志位


<-- Retrofit类的构造函数 -->
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,  
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,  
      Executor callbackExecutor, boolean validateEagerly) {  
    this.callFactory = callFactory;  
    this.baseUrl = baseUrl;  
    this.converterFactories = unmodifiableList(converterFactories); 
    this.adapterFactories = unmodifiableList(adapterFactories);   
    // unmodifiableList(list)近似于UnmodifiableList<E>(list)
    // 作用:创建的新对象能够对list数据进行访问,但不可通过该对象对list集合中的元素进行修改
    this.callbackExecutor = callbackExecutor;  
    this.validateEagerly = validateEagerly;  
  ...
  // 仅贴出关键代码
}

成功建立一个Retrofit对象的标准:配置好Retrofit类里的成员变量,即配置好:

  • serviceMethod:包含所有网络请求信息的对象
  • baseUrl:网络请求的url地址
  • callFactory:网络请求工厂
  • adapterFactories:网络请求适配器工厂的集合
  • converterFactories:数据转换器工厂的集合
  • callbackExecutor:回调方法执行器

对于adapterFactories,该Factory生产callAdapter。

CallAdapter是网络请求执行器(call)的适配器。默认是OkhttpCall,在最初Retrofit打算用OkhttpCall通过ExecutorCallbackCall切换线程,后来发现Rxjava不需要用Handler来切换线程,更加方便,所以后来就用RxjavaCallAdapterFactory将OkhttpCall转换成Rxjava(Scheuler)。

Builder类

<-- Builder-->
public static final class Builder {
    private Platform platform;
    private okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private List<Converter.Factory> converterFactories = new ArrayList<>();
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    private Executor callbackExecutor;
    private boolean validateEagerly;

// 从上面可以发现, Builder类的成员变量与Retrofit类的成员变量是对应的
// 所以Retrofit类的成员变量基本上是通过Builder类进行配置
// 开始看步骤1

<-- 步骤1 -->
// Builder的构造方法(无参)
 public Builder() {
      this(Platform.get());
// 用this调用自己的有参构造方法public Builder(Platform platform) ->>步骤5(看完步骤2、3、4再看)
// 并通过调用Platform.get()传入了Platform对象
// 继续看Platform.get()方法 ->>步骤2
// 记得最后继续看步骤5的Builder有参构造方法
    }
...
}

<-- 步骤2 -->
class Platform {

  private static final Platform PLATFORM = findPlatform();
  // 将findPlatform()赋给静态变量

  static Platform get() {
    return PLATFORM;    
    // 返回静态变量PLATFORM,即findPlatform() ->>步骤3
  }

<-- 步骤3 -->
private static Platform findPlatform() {
    try {

      Class.forName("android.os.Build");
      // Class.forName(xxx.xx.xx)的作用:要求JVM查找并加载指定的类(即JVM会执行该类的静态代码段)
      if (Build.VERSION.SDK_INT != 0) {
        return new Android(); 
        // 此处表示:如果是Android平台,就创建并返回一个Android对象 ->>步骤4
      }
    } catch (ClassNotFoundException ignored) {
    }

    try {
      // 支持Java平台
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }

    try {
      // 支持iOS平台
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }

// 从上面看出:Retrofit2.0支持3个平台:Android平台、Java平台、IOS平台
// 最后返回一个Platform对象(指定了Android平台)给Builder的有参构造方法public Builder(Platform platform)  --> 步骤5
// 说明Builder指定了运行平台为Android
    return new Platform();
  }
...
}

<-- 步骤4 -->
// 用于接收服务器返回数据后进行线程切换在主线程显示结果

static class Android extends Platform {

    @Override
      CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {

      return new ExecutorCallAdapterFactory(callbackExecutor);
    // 创建默认的网络请求适配器工厂
    // 该默认工厂生产的 adapter 会使得Call在异步调用时在指定的 Executor 上执行回调
    // 在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory
    // 采用了策略模式
    
    }

    @Override 
      public Executor defaultCallbackExecutor() {
      // 返回一个默认的回调方法执行器
      // 该执行器作用:切换线程(子->>主线程),并在主线程(UI线程)中执行回调方法
      return new MainThreadExecutor();
    }

    static class MainThreadExecutor implements Executor {
   
      private final Handler handler = new Handler(Looper.getMainLooper());
      // 获取与Android 主线程绑定的Handler 

      @Override 
      public void execute(Runnable r) {
        
        
        handler.post(r);
        // 该Handler是上面获取的与Android 主线程绑定的Handler 
        // 在UI线程进行对网络请求返回数据处理等操作。
      }
    }

// 切换线程的流程:
// 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
//2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程
  }

// 下面继续看步骤5的Builder有参构造方法
<-- 步骤5 -->
//  Builder类的构造函数2(有参)
  public  Builder(Platform platform) {

  // 接收Platform对象(Android平台)
      this.platform = platform;

// 通过传入BuiltInConverters()对象配置数据转换器工厂(converterFactories)

// converterFactories是一个存放数据转换器Converter.Factory的数组
// 配置converterFactories即配置里面的数据转换器
      converterFactories.add(new BuiltInConverters());

// BuiltInConverters是一个内置的数据转换器工厂(继承Converter.Factory类)
// new BuiltInConverters()是为了初始化数据转换器
    }

Builder类的总结:

  • Builder设置了默认的平台类型对象:Android。Retrofit支持IOS,Android和Java。
  • 设置了默认的网络请求适配器工厂:CallAdapterFactory。
  • 设置了默认的数据转换器工厂:converterFactory。用于解析服务器返回的数据。
  • 设置了回调执行器:callbackExecutor。这个用于接收服务器返回数据之后返回主线程进行回调。

注意:Builder方法中,只设置了默认值,并没有真正将这些默认值配置到具体的Retrofit成员变量中。

BaseUrl方法

<-- 步骤1 -->
public Builder baseUrl(String baseUrl) {

      // 把String类型的url参数转化为适合OKhttp的HttpUrl类型
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);     

    // 最终返回带httpUrl类型参数的baseUrl()
    // 下面继续看baseUrl(httpUrl) ->> 步骤2
      return baseUrl(httpUrl);
    }


<-- 步骤2 -->
    public Builder baseUrl(HttpUrl baseUrl) {

      //把URL参数分割成几个路径碎片
      List<String> pathSegments = baseUrl.pathSegments();   

      // 检测最后一个碎片来检查URL参数是不是以"/"结尾
      // 不是就抛出异常    
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }     
      this.baseUrl = baseUrl;
      return this;
    }

baseUrl()用于配置Retrofit类的网络请求url地址:将传入的String类型的Url转化为适合Okhttp的HttpUrl的url,并且检查末尾是不是以/结尾。

GsonConverterFactory.create()方法

public final class GsonConverterFactory extends Converter.Factory {

<-- 步骤1 -->
  public static GsonConverterFactory create() {
    // 创建一个Gson对象
    return create(new Gson()); ->>步骤2
  }

<-- 步骤2 -->
  public static GsonConverterFactory create(Gson gson) {
    // 创建了一个含有Gson对象实例的GsonConverterFactory
    return new GsonConverterFactory(gson); ->>步骤3
  }

  private final Gson gson;

<-- 步骤3 -->
  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }

总之,GsonConverterFactory.creat()方法会创建一个包含Gson对象实例的GsonConverterFactory,并返回给addConverterFactory()。

addConverterFactory()方法

// 将上面创建的GsonConverterFactory放入到 converterFactories数组
// 在第二步放入一个内置的数据转换器工厂BuiltInConverters()后又放入了一个GsonConverterFactory
  public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

addConverterFactory()方法就是将刚创建的包含Gson实例的GsonConverterFactory放入到数据转换器工厂converterFactories数组里。

build()方法

    public Retrofit build() {
 
 <--  配置网络请求执行器(callFactory)-->
      okhttp3.Call.Factory callFactory = this.callFactory;
      // 如果没指定,则默认使用okhttp
      // 所以Retrofit默认使用okhttp进行网络请求
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

 <--  配置回调方法执行器(callbackExecutor)-->
      Executor callbackExecutor = this.callbackExecutor;
      // 如果没指定,则默认使用Platform检测环境时的默认callbackExecutor
      // 即Android默认的callbackExecutor
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

 <--  配置网络请求适配器工厂(CallAdapterFactory-->
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      // 向该集合中添加了步骤2中创建的CallAdapter.Factory请求适配器(添加在集合器末尾)
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    // 请求适配器工厂集合存储顺序:自定义1适配器工厂、自定义2适配器工厂...默认适配器工厂(ExecutorCallAdapterFactory)

 <--  配置数据转换器工厂:converterFactory -->
      // 在步骤2中已经添加了内置的数据转换器BuiltInConverters()(添加到集合器的首位)
      // 在步骤4中又插入了一个Gson的转换器 - GsonConverterFactory(添加到集合器的首二位)
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
      // 数据转换器工厂集合存储的是:默认数据转换器工厂( BuiltInConverters)、自定义1数据转换器工厂(GsonConverterFactory)、自定义2数据转换器工厂....

// 注:
//1. 获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历
// 因此集合中的工厂位置越靠前就拥有越高的使用权限

      // 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

总之,在这个方法中通过前面步骤配置的所有变量,将Retrofit类的所有成员变量都配置完毕。

总结

Retrofit使用建造者模式通过Builder类建立了一个Retrofit实例,具体创建细节是配置了:

  • 平台类型对象(Platform - Android)
  • 网络请求的url地址(baseUrl)
  • 网络请求工厂(callFactory)

默认使用OkHttpCall

  • 网络请求适配器工厂的集合(adapterFactories)

本质是配置了网络请求适配器工厂- 默认是ExecutorCallAdapterFactory

  • 数据转换器工厂的集合(converterFactories)

本质是配置了数据转换器工厂

  • 回调方法执行器(callbackExecutor)

默认回调方法执行器作用是:切换线程(子线程 - 主线程)

由于使用了建造者模式,所以开发者并不需要关心配置细节就可以创建好Retrofit实例。

创建网络请求接口的实例源码解析

创建网络请求接口实例时,调用的是retrofit.create()。

其实Retrofit是通过外观模式和代理模式使用create()方法创建网络请求接口的实例,同时通过网络请求接口里设置的注解戒行了网络参数的配置。

  • 外观模式:定义一个统一接口,外部与通过该统一的接口对子系统里的其他接口进行访问。
  • 代理模式:通过访问代理对象的方式来间接访问目标对象。

retrofit.create(xxx.class)方法

public <T> T create(final Class<T> service) {
    //判断参数是否是个接口
    validateServiceInterface(service);
    // 创建了网络请求接口的动态代理对象,即通过动态代理创建网络请求接口的实例 (并最终返回)
    // 该动态代理是为了拿到网络请求接口实例上所有注解
    return (T) Proxy.newProxyInstance(service.getClassLoader(),// 动态生成接口的实现类 
                                      new Class<?>[] { service },// 动态创建实例
        							  new InvocationHandler() {// 将代理类的实现交给 InvocationHandler类作为具体的实现
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          //invoke()实现中,除了执行真正的逻辑,还可以进行一些有用的操作        
          @Override public @Nullable 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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

在上面的源码中:

  • Proxy.newProxyInstance()⽅法来创建Service实例。这个⽅法会为参数中的多个interface(具体到Retrofit来说,是固定传⼊⼀个interface)创建⼀个对象,这个对象实现了所有interface的每个⽅法,并且每个⽅法的实现都是雷同的:调⽤对象实例内部的⼀个InvocationHandler成员变量的invoke()⽅法,并把⾃⼰的⽅法信息传递进去。这样就在实质上实现了代理逻辑:interface中的⽅法全部由⼀个另外设定的InvocationHandler对象来进⾏代理操作。并且,这些⽅法的具体实现是在运⾏时⽣成interface实例时才确定的,⽽不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是⽹上所说的「动态代理机制」的具体含义。

  • invoke()⽅法中的逻辑,就是Retrofit创建Service实例的关键。这个⽅法内有三⾏关键代码,共同组成了具体逻辑:

1.ServiceMethod的创建:

loadServiceMethod(method)

这⾏代码负责读取interface中原⽅法的信息(包括返回值类型、⽅法注解、参数类型、参数注解),并将这些信息做初步分析。实际返回的是⼀个CallAdapted。

2.OkHttpCall的创建:

new OkhttpCall<>(requestFactory,args,callFactory,responseConverter)

OkHttpCall是retrofit2.Call的⼦类。这⾏代码负责将ServiceMethod解读到的信息(主要是⼀个RequestFactory、⼀个OkHttpClient和⼀个ResponseConverter)封装进OkHttpCall;⽽这个对象可以在需要的时候(例如它的enqueue()⽅法被调⽤的时候),利⽤RequestFactory和OkHttpClient来创建⼀个okhttp3.Call对象,并调⽤这个okhttp3.Call对象来进⾏⽹络请求的发起,然后利⽤ResponseConverter对结果进⾏预处理之后,交回给Retrofit的Callback。

3.adapt()⽅法

serviceMethod.callAdapter.adapt(call)
<--  adapt()详解-->
public <R> Call<R> adapt(Call<R> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);  
      }

   ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.delegate = delegate; 
      // 把上面创建并配置好参数的OkhttpCall对象交给静态代理delegate
      // 静态代理和动态代理都属于代理模式
     // 静态代理作用:代理执行被代理者的方法,且可在要执行的方法前后加入自己的动作,进行对系统功能的拓展
      
      this.callbackExecutor = callbackExecutor;
      // 传入上面定义的回调方法执行器
      // 用于进行线程切换   
    }

这个⽅法会使⽤⼀个CallAdapter对象来把OkHttpCall对象进⾏转换,⽣成⼀个新的对象。默认情况下,返回的是⼀个ExecutorCallbackCall,它的作⽤是把操作切回主线程后再交给Callback。返回对象类型:Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<> 。为什么要切换到主线程再回调呢?OkHttpCall的enqueue()是进行网络异步请求的:当你调用OkHttpCall.enqueue()时,回调的callback是在子线程中,需要通过Handler转换到主线程进行回调。ExecutorCallbackCall就是用于线程回调。

Call call = xxxx.getCall()

  • xxxx对象实际上是动态代理对象Proxy.newProxyInstance(),并不是真正的网络请求接口创建的对象
  • xxxx对象调用getCall()时会被动态代理对象Proxy.newProxyInstance()拦截,然后调用自身的InvocationHandler 的 invoke()
  • invoke(Object proxy, Method method, Object... args)会传入3个参数:Object proxy:(代理对象)、
    Method method(调用的getCall()
    Object... args(方法的参数,即getCall(*)中的*)
  • 接下来利用Java反射获取到getCall()的注解信息,配合args参数创建ServiceMethod对象

最终创建并返回一个OkHttpCall类型的Call对象

  1. OkHttpCall类是OkHttp的包装类
  2. 创建了OkHttpCall类型的Call对象还不能发送网络请求,需要创建Request对象才能发送网络请求

总结

Retrofit采用了外观模式统一调用创建网络请求接口实例和网络请求参数配置的方法,具体细节是:

  • 动态创建网络请求接口的实例(代理模式 - 动态代理
  • 创建 serviceMethod 对象(建造者模式 & 单例模式(缓存机制)
  • serviceMethod 对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 & 数据转换器。(策略模式)
  • serviceMethod 对象加入线程切换的操作,便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理(装饰模式
  • 最终创建并返回一个OkHttpCall类型的网络请求对象。

执行网络请求源码解析

同步请求OkhttpCall.execute()

  • 步骤1:对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析,再根据ServiceMethod对象创建一个OkHttpRequest对象

  • 步骤2:使用OkHttpRequest发送网络请求;

  • 步骤3:对返回的数据使用之前设置的数据转换器(GsonConverterFactory)解析返回的数据,最终得到一个Response<T>对象

源码分析

@Override 
public Response<T> execute() throws IOException {
  okhttp3.Call call;

 // 设置同步锁
  synchronized (this) {
    call = rawCall;
    if (call == null) {
      try {
        call = rawCall = createRawCall();
        // 步骤1:创建一个OkHttp的Request对象请求 -->关注1
      } catch (IOException | RuntimeException e) {
        creationFailure = e;
        throw e;
      }
    }
  }

  return parseResponse(call.execute());
  // 步骤2:调用OkHttpCall的execute()发送网络请求(同步)
  // 步骤3:解析网络请求返回的数据parseResponse() -->关注2
}

<-- 关注1createRawCall()  -->
private okhttp3.Call createRawCall() throws IOException {
  
  Request request = serviceMethod.toRequest(args);
  // 从ServiceMethod的toRequest()返回一个Request对象
  okhttp3.Call call = serviceMethod.callFactory.newCall(request);
  // 根据serviceMethod和request对象创建 一个okhttp3.Request

  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

<--  关注2:parseResponse()-->
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();

  rawResponse = rawResponse.newBuilder()
      .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
      .build();
  // 收到返回数据后进行状态码检查
  // 具体关于状态码说明下面会详细介绍
  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
  }

  if (code == 204 || code == 205) {
    return Response.success(null, rawResponse);
  }

  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
  try {
    T body = serviceMethod.toResponse(catchingBody);
   // 等Http请求返回后 & 通过状态码检查后,将response body传入ServiceMethod中,ServiceMethod通过调用Converter接口(之前设置的GsonConverterFactory)将response body转成一个Java对象,即解析返回的数据
 

// 生成Response类
    return Response.success(body, rawResponse);
  } catch (RuntimeException e) {
    ... // 异常处理
  }
}

以上步骤中常出现ServiceMethod,注:

  • ServiceMethod几乎保存了一个网络请求所需要的数据

  • 发送网络请求时,OkHttpCall需要从ServiceMethod中获得一个Request对象

  • 解析数据时,还需要通过ServiceMethod使用Converter(数据转换器)转换成Java对象进行数据解析

  • 有时候为了提高效率,Retrofit还会对解析过的请求ServiceMethod进行缓存,存放在Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>()

异步请求OkhttpCall.enqueue()

  • 步骤1:对网络请求接口的方法中的每个参数利用对应ParameterHandler进行解析,再根据ServiceMethod对象创建一个OkHttpRequest对象

  • 步骤2::使用OkHttpRequest发送网络请求;

  • 步骤3:对返回的数据使用之前设置的数据转换器(GsonConverterFactory)解析返回的数据,最终得到一个Response<T>对象

  • 步骤4:进行线程切换从而在主线程处理返回的数据结果。(如果使用的是Rxjava则直接回调到主线程)

与同步请求唯一不同之处在于:异步请求会将回调方法交给回调执行器在指定的线程中执行。

源码分析:

<--  call.enqueue()解析  -->
@Override 
public void enqueue(final Callback<T> callback) {

      delegate.enqueue(new Callback<T>() {
     // 使用静态代理 delegate进行异步请求 ->>分析1
     // 等下记得回来
        @Override 
        public void onResponse(Call<T> call, final Response<T> response) {
          // 步骤4:线程切换,从而在主线程显示结果
          callbackExecutor.execute(new Runnable() {
          // 最后Okhttp的异步请求结果返回到callbackExecutor
          // callbackExecutor.execute()通过Handler异步回调将结果传回到主线程进行处理(如显示在Activity等等),即进行了线程切换
          // 具体是如何做线程切换 ->>分析2
              @Override 
               public void run() {
              if (delegate.isCanceled()) {
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override 
        public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }


<-- 分析1:delegate.enqueue()解析 -->
@Override 
public void enqueue(final Callback<T> callback) {
   
    okhttp3.Call call;
    Throwable failure;

// 步骤1:创建OkHttp的Request对象,再封装成OkHttp.call
     // delegate代理在网络请求前的动作:创建OkHttp的Request对象,再封装成OkHttp.call
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
         
          call = rawCall = createRawCall(); 
          // 创建OkHttp的Request对象,再封装成OkHttp.call
         // 方法同发送同步请求,此处不作过多描述  
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }

// 步骤2:发送网络请求
    // delegate是OkHttpcall的静态代理
    // delegate静态代理最终还是调用Okhttp.enqueue进行网络请求
    call.enqueue(new okhttp3.Callback() {
      @Override 
        public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
        
          // 步骤3:解析返回数据
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override 
         public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

// 请回去上面分析1的起点

<-- 分析2:异步请求后的线程切换-->
// 线程切换是通过一开始创建Retrofit对象时Platform在检测到运行环境是Android时进行创建的:(之前已分析过)
// 采用适配器模式
static class Android extends Platform {

    // 创建默认的回调执行器工厂
    // 如果不将RxJava和Retrofit一起使用,一般都是使用该默认的CallAdapter.Factory
    // 后面会对RxJava和Retrofit一起使用的情况进行分析
    @Override
      CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    @Override 
      public Executor defaultCallbackExecutor() {
      // 返回一个默认的回调方法执行器
      // 该执行器负责在主线程(UI线程)中执行回调方法
      return new MainThreadExecutor();
    }

    // 获取主线程Handler
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());


      @Override 
      public void execute(Runnable r) {
        // Retrofit获取了主线程的handler
        // 然后在UI线程执行网络请求回调后的数据显示等操作。
        handler.post(r);
      }
    }

// 切换线程的流程:
// 1. 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
// 2. 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用MainThreadExecutor的execute()通过handler切换到主线程处理返回结果(如显示在Activity等等)
  }

总结

Retrofit 本质上是一个 RESTfulHTTP 网络请求框架的封装,即通过 大量的设计模式 封装了 OkHttp ,使得简洁易用。具体过程如下:

  1. RetrofitHttp请求 抽象 成 Java接口
  2. 在接口里用 注解 描述和配置 网络请求参数
  3. 用动态代理 的方式,动态将网络请求接口的注解 解析 成HTTP请求
  4. 最后执行HTTP请求

最后贴一张非常详细的Retrofit源码分析图:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值