Retrofit源码分析

1.创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
                                 .baseUrl("http://www.baidu.com/")
                                 .addConverterFactory(GsonConverterFactory.create())
                                 .build();
 Retrofit实例是使用建造者模式通过Builder类进行创建的
 <-- 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:回调方法执行器

 callAdapter介绍
 定义:网络请求执行器(Call)的适配器

 Call在Retrofit里默认是OkHttpCall

 在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory


2.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
网络请求适配器工厂:CallAdapterFactory

CallAdapter用于对原始Call进行再次封装,如Call<R>到Observable<R>

数据转换器工厂: converterFactory
回调执行器:callbackExecutor

3.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地址

  4.addConverterFactory()

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


  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;
    }
5.Builder()
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);
    }
    核心代码分析如下:
    6.创建代理对象
    public <T> T create(final Class<T> service) {

           if (validateEagerly) {
          // 判断是否需要提前验证
          eagerlyValidateMethods(service);
          // 具体方法作用:
          // 1. 给接口中每个方法的注解进行解析并得到一个ServiceMethod对象
          // 2. 以Method为键将该对象存入LinkedHashMap集合中
         // 特别注意:如果不是提前验证则进行动态解析对应方法(下面会详细说明),得到一个ServiceMethod对象,最后存入到LinkedHashMap集合中,类似延迟加载(默认)
        }


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

             // 在 InvocationHandler类的invoke()实现中,除了执行真正的逻辑(如再次转发给真正的实现类对象),还可以进行一些有用的操作
             // 如统计执行时间、进行初始化和清理、对接口调用进行检查等。
              @Override
               public Object invoke(Object proxy, Method method, Object... args)
                  throws Throwable {

                // 下面会详细介绍 invoke()的实现
                // 即下面三行代码
                ServiceMethod serviceMethod = loadServiceMethod(method);
                OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
      使用动态代理的好处:调用都会集中转发到 InvocationHandler#invoke ()可集中进行处理,获得网络请求接口实例上的所有注解,更方便封装ServiceMethod

// loadServiceMethod(method)负责加载 ServiceMethod:

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
      // 设置线程同步锁
    synchronized (serviceMethodCache) {

      result = serviceMethodCache.get(method);
      // ServiceMethod类对象采用了单例模式进行创建
      // 即创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例

      // 若没缓存,则通过建造者模式创建 serviceMethod 对象
      if (result == null) {
      // 下面会详细介绍ServiceMethod生成实例的过程
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
// 这里就是上面说的创建实例的缓存机制:采用单例模式从而实现一个 ServiceMethod 对象对应于网络请求接口里的一个方法
// 注:由于每次获取接口实例都是传入 class 对象
// 而 class 对象在进程内单例的,所以获取到它的同一个方法 Method 实例也是单例的,所以这里的缓存是有效的。

根据第一步配置好的ServiceMethod对象和输入的请求参数创建okHttpCall对象
<--OkHttpCall类 -->
public class OkHttpCall {
    private final ServiceMethod<T> serviceMethod; // 含有所有网络请求参数信息的对象
    private final Object[] args; // 网络请求接口的参数
    private okhttp3.Call rawCall; //实际进行网络访问的类
    private Throwable creationFailure; //几个状态标志位
    private boolean executed;
    private volatile boolean canceled;

<--OkHttpCall构造函数 -->
  public OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
    // 传入了配置好的ServiceMethod对象和输入的请求参数
    this.serviceMethod = serviceMethod;
    this.args = args;
}

将第二步创建的OkHttpCall对象传给第一步创建的serviceMethod对象中对应的网络请求适配器工厂的adapt()
返回对象类型:Android默认的是Call<>;若设置了RxJavaCallAdapterFactory,返回的则是Observable<>
<--  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;
      // 传入上面定义的回调方法执行器
      // 用于进行线程切换
    }

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

    动态创建网络请求接口的实例(代理模式 - 动态代理)

    创建 serviceMethod对象建造者模式 & 单例模式(缓存机制))

    对serviceMethod对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 & 数据转换器。(策略模式)

    对serviceMethod对象加入线程切换的操作,便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理(装饰模式)

    最终创建并返回一个OkHttpCall类型的网络请求对象

    异步请求OkHttpCall.enqueue()

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

    步骤2:使用OkHttp的Request发送网络请求;

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

    步骤4:进行线程切换从而在主线程处理返回的数据结果


    <--  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等等)
      }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值