Retrofit 源码解析

来源:互联网 发布:数据库原理与应用 pdf 编辑:程序博客网 时间:2024/06/16 00:11

一、概述





作为 Android 开发者的我们都知道,当我们写一个网络请求的时候,需要写很多代码,很不方便,在这样的背景下,Retrofit 就应运而生了,Retrofit 是当下比较热门的一个框架,如果你不了解 Retrofit 的用法,请点击这里,那本文主要讲解的就是我们的 Retrofit 的原理,在了解他的原理之前,你首先要了解的就是动态代理,Retrofit 之所以简洁,是因为他在运行时帮我们生成代码,让我们少写了很多代码,当他想在运行时插入代码的时候,那么就用到了动态代理,如果不了解动态代理的,请点击这里,那下面我们就进入我们本篇的正文




二、Retrofit 中用到的 http 相关内容讲解





在我们了解 Retrofit 之前,我先说一下我们用到的 http 的知识,首先我们要知道,我们的 http 请求可以把数据放到三个位置:

1、放到 url 的尾部,这种方式对应我们的 Retrofit 的 @Query 注解。

2、放到 Form 表单中,那这种方式对应我们的 @Field 注解,我们要注意的是,我们的 Form 表单中不支持放入文件。

3、放到我们的 body 中,这种方式就比较灵活了,对应我们的 Retrofit 的 @Part 注解,这种方式传递参数我们需要把参数转换成 RequestBody。

注意:我们的第二种和第三种只能用一种,要么用 Form 表单的形式上传,要么用 Multipart ,不过这两种方式都可以与第一种相结合(需要服务端的支持)。


基本的内容我们都了解的差不多了,那下面我们就进入正题,分析我们的一个请求的流程到底是什么样的。



三、源码解析


请求流程:
1、首先我们需要通过 Retrofit.builder 构建一个 Retrofit,看代码:

Retrofit retrofit = new Retrofit.Builder()                            .baseUrl("www.ehuodi.com")                .client(new OkHttpClient())                .addConverterFactory(GsonConverterFactory.create())                .build();





2、创建我们的动态代理类:

EhuodiApi ehuodiApi = retrofit.create(EhuodiApi.class);
Call<String> call = ehuodiApi.selectPreLoading();



3、发送请求:

        call.enqueue(new Callback<String>() {            @Override            public void onResponse(Call<String> call, Response<String> response) {            }            @Override            public void onFailure(Call<String> call, Throwable t) {            }        });


第一步:
那基本请求的流程就在这个里面了,下面我们就一步一步的具体分析每步做了什么,首先我们来看第一步做了什么,看这个步骤之前我先给大家看一下 Retrofit 的成员变量,以及每个成员变量的意义:

public final class Retrofit {  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();//这个主要是缓存的作用,缓存我们生成的代理方法,这也是第二次请求速度快的原因  private final okhttp3.Call.Factory callFactory;    //网络请求工厂,生成 call 的默认用的是 okhttp 的call  private final HttpUrl baseUrl;                //网络请求的 baseUrl,也就是我们第一步指定的 url   private final List<Converter.Factory> converterFactories;    //我们解析器的集合,会存我们手动添加和系统默认的解析器  private final List<CallAdapter.Factory> adapterFactories;    //网络请求的适配工厂,主要是适配平台的  private final Executor callbackExecutor;  //我们回调执行的线程池  private final boolean validateEagerly;         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); // Defensive copy at call site.    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.    this.callbackExecutor = callbackExecutor;    this.validateEagerly = validateEagerly;  }



那上面说了每个成员变量的作用,你可能不是很理解,下面会详细说明每个变量的作用,那下面终于要进入正题了,我们看一下我们的 new Retrofit.builder到底做了什么,下面看代码:

①、调用了 Platform.get 方法
public Builder() {      this(Platform.get());    }
②、通过调用 findPlatform 去选择平台
 private static final Platform PLATFORM = findPlatform();  static Platform get() {    return PLATFORM;  }

③、在 findPlatform 方法中,通过判断是否包含某个类来判断是哪个平台,那下面我们看一下在平台中它做了什么
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) {    }    try {      Class.forName("org.robovm.apple.foundation.NSObject");      return new IOS();    } catch (ClassNotFoundException ignored) {    }    return new Platform();  }


④、在这个方法中我们可以看到,他创建了一个线程池,一个运行在主线程中的线程池,也就是这个线程池的作用导致我们可以在 callback 中处理 UI。
static class Android extends Platform {    @Override public Executor defaultCallbackExecutor() {      return new MainThreadExecutor();    }    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {      return new ExecutorCallAdapterFactory(callbackExecutor);    }    static class MainThreadExecutor implements Executor {      private final Handler handler = new Handler(Looper.getMainLooper());      @Override public void execute(Runnable r) {        handler.post(r);      }    }  }
⑤、
 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());    }


产物:通过 new Request.builder 我们创造出来的东西是一个 Platform 类,在这个类中我们可以通过方法获取一个 ExectorCallAdapterFactory,那这个类的具体内容我们后面再说,然后在我们的解析器中加入了一个 BuiltInConverters 解析器,这是一个默认的解析器。我们这一部分的分析只需要知道我们生成了一个 PlatForm 对象并加入了一个默认的解析器就可以了。


之后我们在看一下接下来的 .baseUrl 做了什么:

public Builder baseUrl(String baseUrl) {      checkNotNull(baseUrl, "baseUrl == null");      HttpUrl httpUrl = HttpUrl.parse(baseUrl);      if (httpUrl == null) {        throw new IllegalArgumentException("Illegal URL: " + baseUrl);      }      return baseUrl(httpUrl);    }
public Builder baseUrl(HttpUrl baseUrl) {      checkNotNull(baseUrl, "baseUrl == null");      List<String> pathSegments = baseUrl.pathSegments();      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);      }      this.baseUrl = baseUrl;      return this;    }


我们可以看到,这部其实很简单,只是给我们的 baseUrl 去进行赋值,而且还做了一些判断。
产物:给 Builder 的 baseUrl 赋值。


之后的几步其实和上面的 .BaseUrl 都是差不多了,基本都是给 Builder 赋值,那 .client 是指定我们的请求的客户端,默认是 okhttpClient,.addConverterFactory 就是增加我们自己的解析器,可以看到上面我们指定的是我们的 Gson 解析。其实就是因为这个建造者模式导致我们的 Retrofit 可扩展性非常好,这也缔造了他的优势扩展性强,那其他 add 的 API 可以自己去看一下,那现在只有最后一步 .build 了,那下面看一下 .build 做了什么:

public Retrofit build() {      if (baseUrl == null) {        throw new IllegalStateException("Base URL required.");      }      okhttp3.Call.Factory callFactory = this.callFactory;    //如果没有指定 call.factory ,那么默认用 okhttpclient      if (callFactory == null) {        callFactory = new OkHttpClient();      }      Executor callbackExecutor = this.callbackExecutor;    //这个是我们回调线程池  ①      if (callbackExecutor == null) {        callbackExecutor = platform.defaultCallbackExecutor();      }      // Make a defensive copy of the adapters and add the default Call adapter.      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);  //②      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));      // Make a defensive copy of the converters.      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,          callbackExecutor, 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); // Defensive copy at call site.    this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.    this.callbackExecutor = callbackExecutor;    this.validateEagerly = validateEagerly;  }


注释说明:
①、我们都知道我们通过 new Retrofit.builder 的产物是一个 Platform ,那在这个时候他通过这个 platform 的方法获取了一个线程池,我们知道我们的 Android 平台创建了一个运行在主线程的 MainThreadExecutor 线程池,那他把这个值付给了 callbackExecutor
②、这个地方就是通过 platform 的方法去获取我们的平台的 calladapter.factory,我们从上面的代码中可以知道 Android 平台创建是 ExecutorCallAdapterFactory 创建之后再把他加入我们的 calladapter.factory 集合中。


产物:可以看到我们第一步就完整的结束了,那我们第一步的产物总体来说就是一个 Retrofit 类,那这个类中有几个关键的东西,一个是我们的解析器(Gson解析器在converterFactories 中),一个是我们的请求callFactory(这个我们知道是 okhttpClient,在callFactory中),一个是我们的回调线程池(MainThreadExecutor 运行在主线程的线程池,在 callbackExecutor 中),一个是我们的平台适配器(Android 平台的ExecutorCallAdapterFactory,在adapterFactories 中 ),那主要的产物也就是这些,下面我们会用到这些产物,请现在记一下方便后面文章的理解,那第一步到此就讲解完成了,下面我们看第二步的讲解。



第二步:

第二步的主要功能就是生成代理类,下面我们看代码:

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);               //③          }        });  }

我们都知道动态代理生成的代理类,在调用被代理的接口中的方法的时候都会执行 InvlcationHandler 中的 invoke 方法,那重点也就到了我们的 invoke 方法啊了,这个方法中首先是做了一些判断,重点来了,判断之后显示通过 loadServiceMethod 生成代理方法,然后通过代理方法生成 OkhttpCall ,最后通过 okhttpCall 返回了一个代理对象
那我们再次进行拆解,我们首先来分析 loadServiceMethod 方法做了什么,下面看代码:

public ServiceMethod build() {      callAdapter = createCallAdapter();          // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器  -->关注点1      responseType = callAdapter.responseType();         // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型      responseConverter = createResponseConverter();          // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器  -->关注点3      // 构造 HTTP 请求时,我们传递的参数都是String      // Retrofit 类提供 converter把传递的参数都转化为 String       // 其余类型的参数都利用 Converter.Factory 的stringConverter 进行转换      // @Body 和 @Part 类型的参数利用Converter.Factory 提供的 requestBodyConverter 进行转换      // 这三种 converter 都是通过“询问”工厂列表进行提供,而工厂列表我们可以在构造 Retrofit 对象时进行添加。       for (Annotation annotation : methodAnnotations) {        parseMethodAnnotation(annotation);      }      // 解析网络请求接口中方法的注解      // 主要是解析获取Http请求的方法     // 注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded     // 处理主要是调用方法 parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) ServiceMethod中的httpMethod、hasBody、relativeUrl、relativeUrlParamNames域进行赋值     int parameterCount = parameterAnnotationsArray.length;     // 获取当前方法的参数数量      parameterHandlers = new ParameterHandler<?>[parameterCount];      for (int p = 0; p < parameterCount; p++) {        Type parameterType = parameterTypes[p];        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];        // 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型        // 该对象的创建过程就是对方法参数中注解进行解析        // 这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url         parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);      }       return new ServiceMethod<>(this);<-- 总结 -->// 1. 根据返回值类型和方法标注从Retrofit对象的的网络请求适配器工厂集合和内容转换器工厂集合中分别获取到该方法对应的网络请求适配器和Response内容转换器;// 2. 根据方法的标注对ServiceMethod的域进行赋值// 3. 最后为每个方法的参数的标注进行解析,获得一个ParameterHandler<?>对象// 该对象保存有一个Request内容转换器——根据参数的类型从Retrofit的内容转换器工厂集合中获取一个Request内容转换器或者一个String内容转换器。    }<-- 关注点1:createCallAdapter() --> private CallAdapter<?> createCallAdapter() {      // 获取网络请求接口里方法的返回值类型      Type returnType = method.getGenericReturnType();            // 获取网络请求接口接口里的注解      // 此处使用的是@Get      Annotation[] annotations = method.getAnnotations();             try {      return retrofit.callAdapter(returnType, annotations);       // 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器      // 下面会详细说明retrofit.callAdapter() -- >关注点2      }...<-- 关注点2:retrofit.callAdapter()  --> public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {    return nextCallAdapter(null, returnType, annotations);  } public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,      Annotation[] annotations) {    // 创建 CallAdapter 如下    // 遍历 CallAdapter.Factory 集合寻找合适的工厂(该工厂集合在第一步构造 Retrofit 对象时进行添加(第一步时已经说明))    // 如果最终没有工厂提供需要的 CallAdapter,将抛出异常    for (int i = start, count = adapterFactories.size(); i < count; i++) {      CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);            if (adapter != null) {        return adapter;      }    }<--   关注点3:createResponseConverter() --> private Converter<ResponseBody, T> createResponseConverter() {      Annotation[] annotations = method.getAnnotations();      try {        // responseConverter 还是由 Retrofit 类提供  -->关注点4        return retrofit.responseBodyConverter(responseType, annotations);      } catch (RuntimeException e) {         throw methodError(e, "Unable to create converter for %s", responseType);      }    }<--   关注点4:responseBodyConverter() -->  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {    return nextResponseBodyConverter(null, type, annotations);  } public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,    int start = converterFactories.indexOf(skipPast) + 1;    for (int i = start, count = converterFactories.size(); i < count; i++) {       // 获取Converter 过程:(和获取 callAdapter 基本一致)         Converter<ResponseBody, ?> converter =          converterFactories.get(i).responseBodyConverter(type, annotations, this);        // 遍历 Converter.Factory 集合并寻找合适的工厂(该工厂集合在构造 Retrofit 对象时进行添加(第一步时已经说明))       // 由于构造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter       // Retrofit - Converters 还提供了 JSON,XML,ProtoBuf 等类型数据的转换功能。       // 继续看responseBodyConverter() -->关注点5        }<--   关注点5:responseBodyConverter() -->@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type,     Annotation[] annotations, Retrofit retrofit) {  TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));  // 根据目标类型,利用 Gson#getAdapter 获取相应的 adapter  return new GsonResponseBodyConverter<>(gson, adapter);}// 做数据转换时调用 Gson 的 API 即可。final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {  private final Gson gson;  private final TypeAdapter<T> adapter;  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {    this.gson = gson;    this.adapter = adapter;  }  @Override    public T convert(ResponseBody value) throws IOException {    JsonReader jsonReader = gson.newJsonReader(value.charStream());    try {      return adapter.read(jsonReader);    } finally {      value.close();    }  }}



至此我们的 loadServiceMethod 方法就分析完成了,其实里面还是有很多东西是值得深入研究的,例如如何通过注解生成代码的,有兴趣的可以去看一下生成代码的代码,应该会很有意思的,那 ① ,我们分析完成了,总结起来就是生成了一个代理方法。

②、主要是生成了一个 okhttpcall

OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {    this.serviceMethod = serviceMethod;    this.args = args;  }

可以看到只是简单的赋值,那我们的 serviceMethod 就是我们的 okhttpCall 的成员变量了

③、这个地方主要是返回了一个包含 call 和 callback 的对象,下面看代码:

return serviceMethod.callAdapter.adapt(okHttpCall);
 public ServiceMethod build() {      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 的 adapt 方法,那我们从上节知道我们的 callAdapter 是通过 createCallAdapter 获取的,那从上节我们也知道,我们的 callAdapter 是通过 Retrofit 获取的,那我们都知道我们 Retrofit 的 callAdapter 是 Android 平台的 ExecutorCallAdapterFactory,那我们只需要看一下 ExecutorCallAdapterFactory 中的 adapt 做了什么就可以了,看代码:
@Override public <R> Call<R> adapt(Call<R> call) {        return new ExecutorCallbackCall<>(callbackExecutor, call);      }

static final class ExecutorCallbackCall<T> implements Call<T> {    final Executor callbackExecutor;    final Call<T> delegate;    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {      this.callbackExecutor = callbackExecutor;      this.delegate = delegate;    }    @Override public void enqueue(final Callback<T> callback) {      if (callback == null) throw new NullPointerException("callback == null");      delegate.enqueue(new Callback<T>() {        @Override public void onResponse(Call<T> call, final Response<T> response) {          callbackExecutor.execute(new Runnable() {            @Override public void run() {              if (delegate.isCanceled()) {                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.                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);            }          });        }      });    }    @Override public boolean isExecuted() {      return delegate.isExecuted();    }    @Override public Response<T> execute() throws IOException {      return delegate.execute();    }    @Override public void cancel() {      delegate.cancel();    }    @Override public boolean isCanceled() {      return delegate.isCanceled();    }    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.    @Override public Call<T> clone() {      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());    }    @Override public Request request() {      return delegate.request();    }  }


可以看到当我们调用 ehuodi.selectPreLoad 方法的时候返回的 call 实际上是一个 ExecutorCallbackCall 对象,在这个对象中有我们请求的 call,也有我们请求的 callback,那这个对象就是我们第二步的产物,第二步的讲解到这里也就结束了。

产物: ExecutorCallbackCall 对象




第三步:


第三步主要就是网络请求了,那我们都知道第二步返回的是一个 ExecutorCallbackCall 对象,那当我们调用 call.enqueue 的时候实际上调用的是 ExecutorCallbackCall  的方法,那我们来看一下 ExecutorCallbackCall 的 enqueue 方法做了什么:

@Override public void enqueue(final Callback<T> callback) {      if (callback == null) throw new NullPointerException("callback == null");      delegate.enqueue(new Callback<T>() {        @Override public void onResponse(Call<T> call, final Response<T> response) {          callbackExecutor.execute(new Runnable() {            @Override public void run() {              if (delegate.isCanceled()) {                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.                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);            }          });        }      });    }




可以看到他调用的是他成员变量 call 的enqueue 的方法,我们都知道这个 call 对象是我们创建的 okhttpcall,那我们继续往下看,看看okhttpcall 做了什么 :






@Override public void enqueue(final Callback<T> callback) {    if (callback == null) throw new NullPointerException("callback == null");    okhttp3.Call call;    Throwable failure;    synchronized (this) {      if (executed) throw new IllegalStateException("Already executed.");      executed = true;      call = rawCall;      failure = creationFailure;      if (call == null && failure == null) {   //如果call 为null 去创建        try {          call = rawCall = createRawCall();     //注解①        } catch (Throwable t) {          failure = creationFailure = t;        }      }    }    if (failure != null) {      callback.onFailure(this, failure);      return;    }    if (canceled) {      call.cancel();    }    call.enqueue(new okhttp3.Callback() {           //在一系列判断之后,说明请求可以发送,那么调用 okhttp 本身的 call 发送请求      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)          throws IOException {        Response<T> response;        try {          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();        }      }    });  }

可以看到,最后调用了 callback 的 onResponse 方法,那这个方法其实也就是回调了我们的 ExecutorCallbackCall 中的 Callback ,那我们接下来看一下代码:


@Override public void enqueue(final Callback<T> callback) {      if (callback == null) throw new NullPointerException("callback == null");      delegate.enqueue(new Callback<T>() {        @Override public void onResponse(Call<T> call, final Response<T> response) {          callbackExecutor.execute(new Runnable() {        //调用了 callbackExector            @Override public void run() {              if (delegate.isCanceled()) {                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.                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);            }          });        }      });    }


我们可以看到关键的地方就是在 onResponse 方法中调用了 callbackExector.execute 方法,我们在前面的分析知道,这个 callbackExector 是一个运行在主线程中的线程池,也就是说我们的 Runnable 中的代码都是在主线程中进行的,这样也就达到了我们线程切换的目的。







总结:

到此,我们的 Retrofit 的流程我们就分析完了,其实还有很多细节性的东西没有分析,之后可能会找个时间解读一下,现在我们总结一下我们的 Retrofit 的工作流程:
1、首先通过 .add 、.client 等方法指定我们要构建什么样的 Retrofit ,其中包括几个重要的部分,解析器,发送请求的平台,回调的执行线程池。
2、通过动态代理生成我们的代理类,在代理类中,我们会去组装我们的请求是什么样子,参数是什么样子,方法是什么样子。
3、我们通过代理类发送请求,然后通过代理类中的线程池切换线程

那本篇文章就写到这里了,总结一个框架的所有东西实在是有点难度,所以,如果有什么不足和不对的地方欢迎指出。