Retrofit2源码分析(一)

前言

很早之前就开始接触Retrofit,自己也写了一个项目,但是一直没有深入研究过源码。


正文

版本

v2.0.2

项目结构

Retrofit2源码分析(一)_第1张图片
image.png

源码文件并不多,所以相对看起来还是比较方便的。


接口

阅读源码,我认为可以先了解作者定义的接口,这样可以有助于我们把握整体的流程,而且优秀的代码也是依赖接口而不是具体的实现。所以要阅读好的三方框架,最好是先了解他的接口,非常有助于源码阅读。

这里主要有4个接口。我简单介绍。

Call

真正发出请求的对象接口

CallAdapter

可以把Call对象转化为另外一个对象,如Observable

Callback

请求回调

Converter

把请求到的数据进行转化

先对所有的接口有个大致的了解


从一个简单的例子入手

  var retrofit = Retrofit.Builder()
                .baseUrl("http://www.baidu.com")
                .build()
        retrofit.create(TestApi::class.java)
                .test("http://www.baidu.com")
                .enqueue(object : Callback {
                    override fun onResponse(call: Call?, response: Response?) {
                    }

                    override fun onFailure(call: Call?, t: Throwable?) {
                    }
                })
...
interface TestApi{
   @GET
    fun test(@Url url:String):Call
    }
第一步: Retrofit构建

从上面例子中可以看出,创建Retrofit时候,只有添加有一个必须添加的baseUrl

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

 okhttp3.Call.Factory callFactory = this.callFactory;
      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 adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

除了可以添加baseUrl,其实还有2个可选的参数可以添加。

  1. Convert 的实现对象的工厂类
  2. CallAdapter的实现对象的工厂类

为了先最简单地了解整个源码的流程,所以这些可选的参数我都先不加。

可以从上面的build的代码中,可以看出,会创建一个
ListList用来存放传进来的参数。所以我们可以知道,Retrofit是可以传入多个CallAdapter.FactoryConverter.Factory

但是这里我们先不管,先往下走。

第二步:使用create创建方法接口
  public  T create(final Class 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);
          }
        });
  }

使用Proxy.newProxyInstance创建了方法接口的一个代理对象,调用接口的方法的时候会进入invoke回调。

在返回这个代理对象之前,其实还有几行代码,我们可以简单看下

  1. 判断接口是否合法,方法数是否>0
    Utils.validateServiceInterface(service)
 static  void validateServiceInterface(Class service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }
  1. 预先加载接口中所有方法
    eagerlyValidateMethods(service);
private void eagerlyValidateMethods(Class service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
第三步:调用接口中的方法

由第二步,我们可以知道,其实调用接口的方法,其实最后是调用了刚才创建的代理对象中的方法,然后进入了invoke方法。所以调用的其实是这一段代码。(一般情况下,是调用下面代码,但是也有一些例外,这里就不多介绍了)

 ServiceMethod serviceMethod = loadServiceMethod(method);
 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 return serviceMethod.callAdapter.adapt(okHttpCall);

由于这3行代码是最最关键的部分,这里做详细的分析。

  1. 加载接口方法
    ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

通过反射的Method对象获取一个ServiceMethod对象。

 注意:ServiceMethod: Adapts an invocation of an interface method into an HTTP call

首先会先从cache中获取一个ServiceMethod,如果没有,就创建一个新的ServiceMethod,再存入cache.

前面已经介绍了,就是ServiceMethod可以进行预先加载,默认使用懒加载,就是调用的时候再去加载,如果对方法调用有时间要求,可以使用预先加载,减少一些时间。

下面来看下ServiceMethod的创建

 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?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }

创建ServiceMethod一共是2个参数,一个是Retrofit对象,一个是Method对象。

可以看到,这个方法中抛出了很多错误,如果使用过retrofit的人,可以看出,都是一些很常见的错误,大部分是注解用错了。

这里最重要的内容有3点

  1. 创建CallAdapter对象
  2. 创建Converter对象
  3. 对接口方法的注释进行解析

我们一个个来看下:

callAdapter = createCallAdapter();

private CallAdapter createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }
...

retrofit.callAdapter(returnType, annotations)

 public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  /**
   * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
   * #callAdapterFactories() factories} except {@code skipPast}.
   *
   * @throws IllegalArgumentException if no call adapter available for {@code type}.
   */
  public CallAdapter nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

创建CallAdapter主要调用Retrofit中的nextCallAdapter,从adapterFactories中获取一个Factory去创建对应的CallAdapter.如果adapterFactories中所有的Factory都无法创建对应的CallAdapter则会报错。

前面介绍到adapterFactories,其实是可以在构建Retrofit对象的时候传入的。但是我们在前面并未传入CallAdapter.Factory,会不会直接报错呢?不会。

 public Retrofit build() {
     ...
      List adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
      ...
    }
  }

在创建adapterFactories对象时,会预先在里面添加一个默认的CallAdapter.Factory


创建Convert的过程和CallAdapter是一致的,我就不过多介绍了

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());
    }
...
List converterFactories = new ArrayList<>(this.converterFactories);
...

这里稍微有点不太一样的地方是,直接在创建Retrofit.Build对象的时候,就先把默认的Convert也就是BuiltInConverters添加到了converterFactories中。


由于Retrofit的注解比较多,所以对接口方法进行解析的过程也比较复杂。也不是整个框架的重点,所以我这里简单介绍下,其中有些地方还是值得我们去学习的。

解析注释,一共分2部分,一个是解析方法上的注释,一个是解析参数上的注释。

 public ServiceMethod build() {
      ...
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      ...
      for (int p = 0; p < parameterCount; p++) {
        ...
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ...
      return new ServiceMethod<>(this);
    }
  1. 方法上的注释:
    parseMethodAnnotation
private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
        if (!Void.class.equals(responseType)) {
          throw methodError("HEAD method must use Void as response type.");
        }
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError("@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

方法上的注释,确实是没啥好说的,就是判断不同的注解进行不同的解析,然后给自己的一些当前变量赋值。我就不说了。

  1. 方法参数上的注释
    parseParameter
private ParameterHandler parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler result = null;
      for (Annotation annotation : annotations) {
        ParameterHandler annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);
        if (annotationAction == null) {
          continue;
        }
        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }
        result = annotationAction;
      }
      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }
      return result;
    }

我就不再深入了,简单点说就是把参数上的注释转化为ParameterHandler对象。来看下ParameterHandler对象是啥。

abstract class ParameterHandler {
  abstract void apply(RequestBuilder builder, T value) throws IOException;
  final ParameterHandler> iterable() {
    return new ParameterHandler>() {
      @Override void apply(RequestBuilder builder, Iterable values) throws IOException {
     ...
    };
  }

  final ParameterHandler array() {
    return new ParameterHandler() {
      @Override void apply(RequestBuilder builder, Object values) throws IOException {
       ...
      }
    };
  }

  static final class RelativeUrl extends ParameterHandler {
    @Override void apply(RequestBuilder builder, Object value) {
      builder.setRelativeUrl(value);
    }
  }

  static final class Header extends ParameterHandler {
    ...
  }

  static final class Path extends ParameterHandler {
    ...
  }

  static final class Query extends ParameterHandler {
   ...
  }

  static final class QueryMap extends ParameterHandler> {
    ...
  }

  static final class Field extends ParameterHandler {
  ...
  }

  static final class FieldMap extends ParameterHandler> {
    ...
  }

  static final class Part extends ParameterHandler {
    ...
  }

  static final class RawPart extends ParameterHandler {
   ...
  }

  static final class PartMap extends ParameterHandler> {
   ...
  }

  static final class Body extends ParameterHandler {
    ...
}
 
 

所有的注解对应的都有自己的一个ParameterHandler实现。然后在里面进行解析。

解析方法注释得到的参数,以及解析方法参数的注释得到的ParameterHandler都是为了构建Request对象,代码如下:

 Request toRequest(Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler[] handlers = (ParameterHandler[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }
 
 

其中handlers[p].apply(requestBuilder, args[p]);是循环调用ParameterHandler这个抽象类的抽象方法。这里是值得我们学习的,依赖抽象类和接口,而不依赖具体的实现。

下面我们可以再回过头来看
/** Adapts an invocation of an interface method into an HTTP call. */
官方对ServiceMethod的说明。
其实就我个人理解,是不是改成
/** Adapts an invocation of an interface method into an HTTP request. */
会更好点,因为ServiceMethod是把接口方法最终转化为一个Request对象而不是一个Call对象,当然也只是个人的理解。


  1. 创建OkHttpCall对象
    OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
 OkHttpCall(ServiceMethod serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

OkHttpCall的构造方法很简单,OkHttpCall实现了Call接口。

  1. CallAdapter对Call对象进行转换

在介绍这个之前,我们再回顾下前面的默认的CallAdapter。
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

这里需要了解Platform

class Platform {
 ..
  }
  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);
      }
    }
  }

  static class IOS extends Platform {
    ...
  }
}

对不同的平台进行不同的处理。这里肯定是Android平台,所以应该调用Android中的方法。

所以,默认的CallAdapter.FactoryExecutorCallAdapterFactory
下面我们继续刚才最重要的3句代码中的最后一句代码
return serviceMethod.callAdapter.adapt(okHttpCall);

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
 ...
  @Override
  public CallAdapter> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public  Call adapt(Call call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

  static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback callback) {
      if (callback == null) throw new NullPointerException("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()) {
                // 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 call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }
...

使用adapt方法后,返回了ExecutorCallbackCall这个对象

第四步:enqueue发送请求(execute大同小异)

具体的代码请看上面,从ExecutorCallbackCall开始。
前面一步步走下来,我们已经知道,调用接口方法后,真正返回的是ExecutorCallbackCall对象。

调用enqueue方法,其实是调用创建ExecutorCallbackCall对象时传入的Call对象。我们在前面第三步时解析了最关键的三句代码,了解到了其实这里的Call对象,就是OkHttpCall对象。

@Override public void enqueue(final Callback callback) {
    ...
    call = rawCall = createRawCall();
    ...
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
          ...
          response = parseResponse(rawResponse);
         ...
    });
  }
...
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;
  }
...
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
     ...
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
     ...
  }

其中最重要的2个方法就是

  1. createRawCall
  2. parseResponse

这里我们分别来分析下。


createRawCall
这里主要调用了serviceMethod.toRequest(args)其实我们在前面已经介绍过了,ServiceMethod中的toRequest就是把前面解析完成的参数,转化为对应的Request,这里就不多说了。

这里我们还要了解serviceMethod.callFactory是什么?
ServiceMethod.java

...
 ServiceMethod(Builder builder) {
    this.callFactory = builder.retrofit.callFactory();
     ...
  }

Retrofit.java

...
 public Builder client(OkHttpClient client) {
      return callFactory(checkNotNull(client, "client == null"));
    }

    /**
     * Specify a custom call factory for creating {@link Call} instances.
     * 

* Note: Calling {@link #client} automatically sets this value. */ public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; } ... public Retrofit build() { ... okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } ... ...

由上代码可看出,ServiceMethod中的callFactory就是Retrofit中的callFactory,可以在构建Retrofit对象的时候传入,不传入默认为OkHttpClient

所以
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
这里的serviceMethod.callFactory其实就是OkHttpClient然后创建了一个Call对象。真正发起请求的也是这个Call对象。

这里可能会看起来有点糊涂,因为这里的Callokhttp3.Call,而前面一直在说的Callretrofit2.Call大家不要把这2个搞混了。

我们可以把这2个做一下对比会发现,它们的方法基本一致。

Retrofit我们可以理解为在okhttp3外面的一层封装,真正去发生http请求的还是原来的okhttp3


parseResponse
代码在上面已贴出,其中最重要的一句是:
T body = serviceMethod.toResponse(catchingBody);

...
this.responseConverter = builder.responseConverter;
...
T toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }
...

使用Convert对象把ResponseBody转化为另一个对象。由代码可以看出,ServiceMethod中的responseConverter也是来自Retrofit对象。也就是前面介绍的默认的Convert.Factory对象,也就是BuiltInConverters,产生的Convert对象。

final class BuiltInConverters extends Converter.Factory {
  @Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
        return StreamingResponseBodyConverter.INSTANCE;
      }
      return BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

ServiceMethod中会根据方法的返回类型,在里面获取到对应的Convert对象。如果返回的类型没有相应的Convert则会返回null。
Retrofit.java

 public  Converter nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter converter =
        //**在这里真正去获取对应的Convert**
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter) converter;
      }
    }

    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
        .append(type)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

从代码中可以看出,如果返回为null,那么会从下一个Convert.Factory中去获取对应的Convert由于我们前面并未添加Convert.Factory,所以这里只有一个默认的BuiltInConverters,并且它只支持返回值是ResponseBody,Void这2种类型的或者注释中有Streaming的方法,否者会报错。

第五步:在Callback接口中对转换后的对象进行处理

到了这一步的时候其实源码代码已经分析的差不多了。但是前面提到的默认的
CallAdapter.Factory也就是ExecutorCallAdapterFactory中其实有个细节刚才我没有细讲,现在可以回过去看。

 @Override public void enqueue(final Callback callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
        //**使用callbackExecutor去执行真正的callback中的onResponse和onFailure**
          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 call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });

我们往回追溯,看下callbackExecutor是什么

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

defaultCallbackExecutor其实就是把Runnable抛到主线程中去执行。
所以在我们自己的Callback中的onResponseonFailure已经都是在主线程中执行了。

总结

Retrofit的源码相对来说是比较少的,非常适合新手阅读(包括我),可以快速体验阅读源码的乐趣,感觉对整个框架的使用都会得心应手。

另外自己也感受到了阅读源码的3个好方法。

  1. 先了解所有的接口,对整个框架有个大致的了解
  2. 可以写一个简单的demo,一步步深入
  3. 从后往前,想要知道一个变量的由来,可以往前追溯

你可能感兴趣的:(Retrofit2源码分析(一))