Retrofit2实例源码浅析

从Retrofit最基本的用法着手,一步步分析内部调用流程。

此处以一个POST请求为例:

一.构建Retrofit

OkHttpClient client = new OkHttpClient();
retrofit = new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build();

二.构建接口

public interface ApiService {
    @FormUrlEncoded
    @POST("user/info")
    Call loadUserInfo(@FieldMap Map map);
}

三.发起请求

Call call = retrofit.create(ApiService.class).loadUserInfo(map);
call.enqueue(new Callback() {
    @Override
    public void onResponse(Call call, Response response) {
    }

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

源码分析

结合上面的例子,看看每一个步骤中源码做了哪些操作

一.构建Retrofit

1)new Retrofit.Builder()

Retrofit通过Builder构建,先看Retrofit.Builder的构造方法

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

构造方法中保存了一个Platform对象,看看Platform是什么

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }
  ···
}

可以看到get()是获取静态成员变量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) {
    }
    return new Platform();
  }

该方法通过反射类名是否存在判断当前运行于哪个平台,这里是Android

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      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方法内部定义了一个线程池,CallbackExecutor顾名思义就是决定处理response回调时所处线程。这里的线程池MainThreadExecutor创建了一个主线程handler,当执行runnable时,会将任务扔到主线程执行。

defaultCallAdapterFactory方法创建一个ExecutorCallAdapterFactory对象,它继承自CallAdapter.Factory,后面再分析。

2)baseUrl(BASE_URL)

baseUrl方法其实就是将传入的url转换成okhttp3中的HttpUrl对象保存起来

public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      // 调用okhttp3的HttpUrl.parse方法转换url
      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 pathSegments = baseUrl.pathSegments();
      // 检查url格式,必须是以"/"结尾
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
}

3)addConverterFactory(GsonConverterFactory.create())

添加转换器工厂,用于请求、响应对象的序列化和反序列化

public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
}

Retrofit2实例源码浅析_第1张图片

可以看看本例中传入的GsonConverterFactory,它继承Converter.Factory并实现了其中两个方法,responseBodyConverter和requestBodyConverter:

@Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

  @Override
  public Converter requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }

分别创建并返回Converter接口的实现类GsonRequestBodyConverter和GsonResponseBodyConverter。GsonRequestBodyConverter负责将请求参数转换成RequestBody,GsonResponseBodyConverter负责将ResponseBody映射成实体类。

public interface Converter {
  T convert(F value) throws IOException;
}

4)client(client)

保存开头创建的OkHttpClient,实际保存okhttp3.Call.Factory接口的实现,后续调用它的newCall方法返回RealCall对象。

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

public Builder callFactory(okhttp3.Call.Factory factory) {
      this.callFactory = checkNotNull(factory, "factory == null");
      return this;
}

5)build()

根据前面设置的参数构建Retrofit实例

public Retrofit build() {
      // 可以看出baseUrl是必填参数
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      // 若开头未设置client,这里也会自动创建
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      // 若为设置callbackExecutor,则调用platform.defaultCallbackExecutor方法,通过上文可以知道,这里返回MainThreadExecutor线程池
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // 创建自定义的调用适配器列表的副本,并添加默认调用适配器,默认适配器中保存的线程池即MainThreadExecutor
      List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

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

      // 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());
      converterFactories.addAll(this.converterFactories);

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

Retrofit构造方法

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List converterFactories, List callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
}

这里传入的List为不可修改的List。validateEagerly为true的话,在后续的create方法中会立即进行解析ApiService中定义的method,该值默认为false。

以上就是Retrofit初始化时,一些主要的配置项。本例中没有使用addCallAdapterFactory,可以通过该方法配置RxJava使用(需要引入rxjava库依赖),例如:

.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

二.构建接口

上面的例子中定义了一个接口,并且声明了一个方法,Retrofit会根据这个方法上的注解、参数以及返回值进行解析,通过动态代理转换成具体的请求。

三.发起请求

1)retrofit.create(ApiService.class)

创建定义的接口的代理实例

public  T create(final Class service) {
    // 对传入的类进行检查,必须是interface且没有继承扩展其他接口
    Utils.validateServiceInterface(service);
    // validateEagerly可在Retrofit初始化时设置,默认为false
    if (validateEagerly) {
      // 立即加载接口中声明的方法,将方法解析成对应的ServiceMethod对象
      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 {
            // 执行代理类会回调此方法。参数1为代理类实例;参数2为调用的方法;参数3为调用方法中传入的参数
            ···
          }
        });
}

2)loadUserInfo(map)

获得代理类后,调用loadUserInfo方法,返回Call对象。当执行时即触发了代理回调方法invoke()

new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            // 判断该方法所在类是否是Object
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // isDefaultMethod默认返回false
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            // 以下三行是关键
            ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
} 
  

该回调中前面对method进行合法性检查,后面三行是关键,依次分析:

1.先看loadServiceMethod方法
ServiceMethod loadServiceMethod(Method method) {
    // 先从缓存中查找(serviceMethodCache为ConcurrentHashMap,key为method,value为ServiceMethod)
    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();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
}

接下来看ServiceMethod的构建方法:

Builder的构造方法

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit; // 持有retrofit引用
      this.method = method;  // 持有调用的method的引用
      this.methodAnnotations = method.getAnnotations(); // 获取所有的注解
      this.parameterTypes = method.getGenericParameterTypes(); // 获取该方法的参数的参数化的类型
      this.parameterAnnotationsArray = method.getParameterAnnotations(); // 获取参数注解
}

build()方法中解析的东西比较多,拆开来看:

  • 首先生成CallAdapter实例
public ServiceMethod build() {
      callAdapter = createCallAdapter();
      ···
}
private CallAdapter createCallAdapter() {
      // 获取该method的返回值类型
      Type returnType = method.getGenericReturnType();
      // 检查类型合法性,若是通配符类型或类型变量类型则抛异常。注意若是参数化类型或泛型数组类型,还会检查泛型参数和数组元素类型,同样不能是通配符、类型变量类型。
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      // 该method必须有返回,不能是void
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      // 获取该method上的注解
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        return (CallAdapter) 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方法,并传入返回值类型和方法上的注解

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

public CallAdapter nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    // 因为传入的skipPast为null,所以start = -1 + 1,即0
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      // 本例中没有额外添加自定义的CallAdapter.Factory,所以此时callAdapterFactories中只有一个元素,即Retrofit初始化时默认添加的ExecutorCallAdapterFactory
      // 若有自定义的CallAdapter.Factory,在get方法中根据returnType、annotations参数决定能否处理,不能处理则get方法返回null,继续往下遍历
      CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

    // 未找到合法的CallAdapter,则拼接异常信息抛出异常
    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(callAdapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(callAdapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
}

接着看ExecutorCallAdapterFactory的get方法:

@Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    // getRawType方法根据Type获取method返回值的类(判断Type属于哪种类型,再返回对应的类)
    // 这里限制method的返回值必须是retrofit2.Call,不满足的话返回null,交由下一个CallAdapter.Factory处理
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    // getCallResponseType先判断returnType是否是参数化类型,不是则抛异常(所以method返回的应该是Call这种形式)
    // 然后返回Call中T的类型,若T为通配符类型,则返回它的邻近上界的类型
    final Type responseType = Utils.getCallResponseType(returnType);
    // 创建并返回CallAdapter对象
    return new CallAdapter>() {
      @Override public Type responseType() {
        // 即返回上文获得的参数类型
        return responseType;
      }

      @Override public Call adapt(Call call) {
        // ExecutorCallbackCall可以理解为call的代理类,包装了callbackExecutor即MainThreadExecutor和这里的call
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
} 
  

到这里生成并返回callAdapter实例,之后保存response的类型
response即在method定义时设置的返回对象。例如Call,response即为String。在本例中Call,response即为UserInfo。

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      // 这里获取保存response的类型,即Call<>的<>中参数化类型
      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?");
      }
      ···
}
  • 接着生成Converter实例
public ServiceMethod build() {
    ···
    responseConverter = createResponseConverter();
    ···
}
private Converter createResponseConverter() {
      // 获取method上所有注解
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.responseBodyConverter(responseType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      }
}

最终调用到retrofit的nextResponseBodyConverter方法

public  Converter responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
}

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

    // skipPast为null,因此这里start值为0
    int start = converterFactories.indexOf(skipPast) + 1;
    // 遍历converterFactories
    // 从上文的构建Retrofit可以知道,第一个元素为默认的BuiltInConverters,第二个元素为本例添加的GsonConverterFactory
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      // responseBodyConverter方法中须判断type、annotations是否是该Converter.Factory能够处理的,不能处理则返回null,遍历下一个Converter.Factory
      Converter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter) 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());
}

① 先分析BuiltInConverters

@Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    // 判断response类型,即Call中的T的类型
    // response若为ResponseBody或继承自ResponseBody
    if (type == ResponseBody.class) {
      // 判断method上的注解是否有Streaming注解,返回对应的Converter。Streaming的作用是标记不将body转换为byte[]
      // StreamingResponseBodyConverter的convert方法中直接原样返回ResponseBody,不进行额外处理
      // 而BufferingResponseBodyConverter的convert方法会将ResponseBody读进Buffer中
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    // 若为Call
    if (type == Void.class) {
      // VoidResponseBodyConverter的convert方法中会关闭ResponseBody的字节流和清除缓冲区,最后return null
      return VoidResponseBodyConverter.INSTANCE;
    }
    // 都不为以上类型,返回null,交由下一个Converter.Factory处理
    return null;
}

Retrofit默认自带的BuiltInConverters就是判断设置的response的类型,返回对应的Converter。本例为UserInfo,因此没有符合条件的Converter,传到下一个Converter.Factory。

② 接着分析GsonConverterFactory

@Override
  public Converter responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
}

它使用了Google Gson库将ResponseBody转换为实体类,在本例中会转换为UserInfo。

经过上面的代码,responseConverter被赋值为GsonResponseBodyConverter。回到ServiceMethod的build方法继续往下分析。

  • 解析method上的注解
public ServiceMethod build() {
  ···
  // 依次解析method上的注解,根据注解类型赋值httpMethod、hasBody、isMultipart、isFormEncoded等成员变量
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  // 对解析后的结果检查
  if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  // 不带request body的method不能设置Multipart和FormUrlEncoded注解
  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).");
        }
  }
  ··· 
}
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) {
        // 本例使用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) {
        // Multipart和FormUrlEncoded不能同时使用,本例使用FormUrlEncoded
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
}

在本例为POST请求,因此传入的三个参数分别是”POST”、”user/info”、true:

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      if (this.httpMethod != null) {
        throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
            this.httpMethod, httpMethod);
      }
      this.httpMethod = httpMethod;
      this.hasBody = hasBody;

      if (value.isEmpty()) {
        return;
      }

      // Get the relative URL path and existing query string, if present.
      int question = value.indexOf('?');
      // 判断url是否带"?"和"key=value&key=value"
      if (question != -1 && question < value.length() - 1) {
        // Ensure the query string does not have any named parameters.
        // 对于url后拼接的k=v query参数,不能使用"{}"占位,若需要使用的话可以通过Query注解
        String queryParams = value.substring(question + 1);
        Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
        if (queryParamMatcher.find()) {
          throw methodError("URL query string \"%s\" must not have replace block. "
              + "For dynamic query parameters use @Query.", queryParams);
        }
      }

      // 这里相对url即赋值为"user/info"
      this.relativeUrl = value;
      // 若url path中有用到"{}"占位,将路径参数保存在这个Set中
      this.relativeUrlParamNames = parsePathParameters(value);
}

执行到这里解析完了method上的注解,然后开始解析method参数上的注解。

  • 解析parameter上的注解
public ServiceMethod build() {
      ···
      // 获取参数个数
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        // 获取参数类型
        Type parameterType = parameterTypes[p];
        // 与检查method的returnType一样检查类型
        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对象
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ···
}

Retrofit利用ParameterHandler对象保存和处理method中的参数上的注解,看看它是如何构造的:

private ParameterHandler parseParameter(
        int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler result = null;
      // 遍历注解
      for (Annotation annotation : annotations) {
        ParameterHandler annotationAction = parseParameterAnnotation(
            p, parameterType, annotations, annotation);

        // 过滤非Retrofit定义的注解
        if (annotationAction == null) {
          continue;
        }

        // 一个参数最多只能有一个Retrofit的注解
        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }

        result = annotationAction;
      }

      // 该参数上一个Retrofit的注解都没有
      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }

      // 返回构造的ParameterHandler对象
      return result;
}

又调用parseParameterAnnotation方法,依次传入注解解析:
(该方法比较长,就不贴出完整代码)

private ParameterHandler parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
        // 以下判断根据不同的注解创建返回对应的ParameterHandler子类,本例使用了FieldMap注解,会创建ParameterHandler.FieldMap对象
        if (annotation instanceof Url) {
            // 1.先检查是否有不同的注解使用冲突
            // 2.赋值gotUrl成员变量为true
            // 3.判断参数类型是否为HttpUrl、String、URI、Uri,是则创建返回RelativeUrl对象,否则抛异常
        } else if (annotation instanceof Path) {
            // 1.先检查是否有不同的注解使用冲突
            // 2.赋值gotPath成员变量为true
            // 3.取出Path注解的value,校验value是否合法和relativeUrlParamNames中是否存在占位相同的名称
            // 4.获取Converter。遍历converterFactories,根据type和annotations查找Converter,若没有合适的Converter,则使用默认的ToStringConverter对象
            // 5.创建ParameterHandler.Path对象并传入Path注解的value、encoded和上面的converter,最后返回ParameterHandler.Path
        } else if (annotation instanceof Query) {
            // 1.取出Query注解的value、encoded,gotQuery成员变量赋值为true
            // 2.同上获取到ToStringConverter,创建ParameterHandler.Query对象并传入Query注解的value、encoded和converter,最后返回ParameterHandler.Query
        } else if (annotation instanceof QueryName) {
            // 1.取出QueryName注解的encoded,gotQuery成员变量赋值为true
            // 2.同上获取到ToStringConverter,创建ParameterHandler.QueryName对象并传入Query注解的value、encoded和converter,最后返回ParameterHandler.QueryName
        } else if (annotation instanceof QueryMap) {
            // 1.检查参数是否合法,必须是Map且key为String类型
            // 2.通过Map中value的类型获取Converter,这里同上获取到ToStringConverter
            // 3.创建ParameterHandler.QueryMap并传入QueryMap注解的encoded和converter,最后返回
        } else if (annotation instanceof Header) {
            // 与上面类似,不再一一分析。都是判断参数类型或参数化类型中的泛型类型,获取converter,再创建返回ParameterHandler对应子类。
        } else if (annotation instanceof HeaderMap) {
        } else if (annotation instanceof Field) {
        } else if (annotation instanceof FieldMap) {
        } else if (annotation instanceof Part) {
        } else if (annotation instanceof PartMap) {
        } else if (annotation instanceof Body) {
        }
        return null; // Not a Retrofit annotation.
}

parseParameterAnnotation方法中判断不同的注解类型创建对应的ParameterHandler子类,若不是Retrofit中定义的注解则返回null。
这里单独分析下本例使用的FieldMap注解:

else if (annotation instanceof FieldMap) {
        // 在parseMethodAnnotation方法中判断FormUrlEncoded注解时设置isFormEncoded为true
        // 使用FieldMap注解,必须同时使用FormUrlEncoded注解
        if (!isFormEncoded) {
          throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
        }
        // 获取该参数的class,若参数为泛型或数组或通配符,则获取泛型的类型的class或元素的class或邻近父类的class
        Class rawParameterType = Utils.getRawType(type);
        // 比较参数的class,必须是Map或其子类
        if (!Map.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(p, "@FieldMap parameter type must be Map.");
        }
        Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
        // 比较参数的Type,必须是参数化类型,即有<>
        if (!(mapType instanceof ParameterizedType)) {
          throw parameterError(p,
              "Map must include generic types (e.g., Map)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) mapType;
        // 获取Map中key的类型
        Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
        if (String.class != keyType) {
          throw parameterError(p, "@FieldMap keys must be of type String: " + keyType);
        }
        // 获取Map中value的类型
        Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
        // 根据value的类型查找converter,这里取到的是ToStringConverter
        Converter valueConverter =
            retrofit.stringConverter(valueType, annotations);

        // 赋值gotField成员变量为true
        gotField = true;
        // 创建返回ParameterHandler.FieldMap对象
        return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded());
}

执行到这里每个ParameterHandler对应一个参数的注解解析,依次保存在parameterHandlers数组中。

  • 校验和实例化ServiceMethod

接着看ServiceMethod的构建中剩下的代码:

public ServiceMethod build() {
      ···
      // 对配合使用的注解的检查,有的注解需要配合使用,有的注解不能同时使用。在上面的解析过程中也会进行部分检查。
      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的创建过程,回到Retrofit的create方法中继续往下分析。

2.接着创建OkHttpCall对象
ServiceMethod serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall); 
  

OkHttpCall构造方法

OkHttpCall(ServiceMethod serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod; // 持有loadServiceMethod返回的serviceMethod
    this.args = args; // 持有调用loadUserInfo接口方法传入的参数args
}

OkHttpCall实现了retrofit2.Call接口,retrofit2.Call和okhttp3.Call方法类似,作用相当于对okhttp3做了一层装饰。

3.最后返回T的实例

serviceMethod.adapt(okHttpCall),本例转换为Call返回。

T adapt(Call call) {
    return callAdapter.adapt(call);
}

调用了serviceMethod构建时获取的callAdapter中的adapt方法:

@Override public Call adapt(Call call) {
    // ExecutorCallbackCall可以理解为call的代理类,包装了callbackExecutor即MainThreadExecutor和这里的call
    return new ExecutorCallbackCall<>(callbackExecutor, call);
} 
  

最终返回ExecutorCallbackCall对象。

3)call.enqueue(myCallback)

加入异步队列发起请求,这里的call即上文创建的ExecutorCallbackCall。

@Override public void enqueue(final Callback callback) {
      checkNotNull(callback, "callback == null");

      // 调用委托类,即OkHttpCall的enqueue方法
      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          // callbackExecutor为MainThreadExecutor,该线程池持有主线程handler,调用execute方法时会将runnable通过handler扔到主线程执行
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                // 模拟OkHttp在取消时抛出/传递IOException的行为
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                // 将response回调传递出去
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              // 在主线程回调onFailure
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
}

接下来看OkHttpCall.enqueue方法

@Override public void enqueue(final Callback callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      // executed成员变量标识是否已执行
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      // 开始默认都为空
      if (call == null && failure == null) {
        try {
          // 创建okhttp3.Call对象
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    // 若createRawCall这步发生异常,则回调onFailure,然后结束
    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    // canceled成员变量标识是否已取消该请求,默认为false,可通过cancel()取消请求并将其置为true
    if (canceled) {
      // 调用okhttp3.Call的cancel方法
      call.cancel();
    }

    // 最终调用okhttp3.Call的enqueue发起异步请求
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response response;
        try {
          // 解析okhttp3.Response,转换为retrofit2.Response返回
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          // 解析发生异常,调用失败回调
          callFailure(e);
          return;
        }

        try {
          // onResponse回调,将转换后的response传出
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

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

可以看出enqueue方法就是创建okhttp3.Call对象,再调用它的enqueue方法,在onResponse回调中将okhttp3.Response转换为retrofit2.Response。

  • 接下来看下createRawCall方法:
private okhttp3.Call createRawCall() throws IOException {
    // 通过serviceMethod来创建okhttp3.Call
    okhttp3.Call call = serviceMethod.toCall(args);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

ServiceMethod的toCall方法:

/** Builds an HTTP request from method arguments. */
okhttp3.Call toCall(@Nullable 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;

    // 校验参数个数和ParameterHandler个数是否一致
    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    // 遍历parameterHandlers,依次调用ParameterHandler的apply方法
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    // 这里callFactory即为OkHttpClient实例,调用OkHttpClient的newCall方法创建okhttp3.Call
    // requestBuilder.build()方法中会保存的参数根据构建HttpUrl和RequestBody,最后再构建okhttp3.Request
    return callFactory.newCall(requestBuilder.build());
} 
  

ParameterHandler的apply方法为抽象方法,由其子类具体实现。本例中定义的参数为@FieldMap Map map,因此这里执行ParameterHandler.FieldMap的apply方法:

@Override void apply(RequestBuilder builder, @Nullable Map value)
        throws IOException {
      if (value == null) {
        throw new IllegalArgumentException("Field map was null.");
      }

      // 遍历Map
      for (Map.Entry entry : value.entrySet()) {
        String entryKey = entry.getKey();
        if (entryKey == null) {
          throw new IllegalArgumentException("Field map contained null key.");
        }
        T entryValue = entry.getValue();
        if (entryValue == null) {
          throw new IllegalArgumentException(
              "Field map contained null value for key '" + entryKey + "'.");
        }

        // 通过Converter.convert方法将Map中的value转换为String类型
        String fieldEntry = valueConverter.convert(entryValue);
        if (fieldEntry == null) {
          throw new IllegalArgumentException("Field map value '"
              + entryValue
              + "' converted to null by "
              + valueConverter.getClass().getName()
              + " for key '"
              + entryKey
              + "'.");
        }

        // 将key、value保存进RequestBuilder的formBuilder成员中,formBuilder使用两个ArrayList分别来保存key、value。encoded表示是否对key、value做Encoded处理
        builder.addFormField(entryKey, fieldEntry, encoded);
      }
    }
}

apply方法中的valueConverter即为ToStringConverter:

@Override public String convert(Object value) {
      return value.toString();
}
  • 再来看下parseResponse方法

这里先看下retrofit2.Response类:

public final class Response<T> {
    private final okhttp3.Response rawResponse; // 持有响应的okhttp3.Response对象
    private final @Nullable T body; // HTTP请求正常情况下,持有定义的泛型对象
    private final @Nullable ResponseBody errorBody; // HTTP请求错误下,持有okhttp3.ResponseBody对象
    ···
}

OkHttpCall的parseResponse方法:

Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    // 复制一个ResponseBody,将body成员替换为NoContentResponseBody对象
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    // 获取HTTP状态码
    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        // 新创建一个ResponseBody保存body
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        // 返回retrofit2.Response对象,rawResponse赋值为rawResponse、body赋值为null、errorBody赋值为bufferedBody
        return Response.error(bufferedBody, rawResponse);
      } finally {
        // 关闭rawBody中的BufferedSource,释放资源
        rawBody.close();
      }
    }

    // HTTP请求成功,但是没有实体返回
    if (code == 204 || code == 205) {
      // 关闭流、释放资源
      rawBody.close();
      // 创建返回retrofit2.Response,它的rawResponse成员赋值为rawResponse,其他成员均为null
      return Response.success(null, rawResponse);
    }

    // 创建ExceptionCatchingRequestBody作为rawBody的代理类,内部有一个IOException异常变量,记录okio操作出现的IO异常
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      // 获取接口方法定义时的响应实体类,本例中为UserInfo
      T body = serviceMethod.toResponse(catchingBody);
      //创建返回retrofit2.Response,它的rawResponse成员赋值为rawResponse,body赋值为body,errorBody为null
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      // 抛出记录的IOException若有
      catchingBody.throwIfCaught();
      throw e;
    }
}

继续看ServiceMethod的toResponse方法:

/** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}

这里的responseConverter即为GsonResponseBodyConverter,它的convert方法使用Gson将ResponseBody正文转换为对应的实体类,即本例中的UserInfo对象。

到这里整个请求就完成了,将转换后的retrofit2.Response通过Callback传给了调用者。

你可能感兴趣的:(Android)