Retrofit源码分析

  • 本文概述

    Retrofit作为主流的网络框架,采用注解和接口的方式封装请求,使得调用过程变得优雅又简洁,优雅的背后肯定是卓越的设计,所以从源码角度分析一下Retrofit是如何做到的,整理成文。

  • 使用回顾

    public interface GitHubService {
    
        @GET("group/{id}/users?sort=desc")
        Call<List<User>> groupList(@Path("id") int groupId);
    
        /**
         * 和上面的是一样的意义
         *
         * @param groupId
         * @param sort
         * @return
         */
        @GET("group/{id}/users")
        Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
    
        /**
         * 相当于group/{id}/users?options.key[0]=options.value[0] & options.key[1]=options.value[1] & ...
         *
         * @param groupId
         * @param options
         * @return
         */
        @GET("group/{id}/users")
        Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
    
        @POST("users/new")
        Call<User> createUser(@Body User user);
    
        @FormUrlEncoded
        @POST("user/edit")
        Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
    
        @Multipart
        @PUT("user/photo")
        Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
    
        /**
         * 静态Header
         * @return
         */
        @Headers("Cache-Control: max-age=640000")
        @GET("widget/list")
        Call<List<User>> widgetList();
    
        @Headers({
                "Accept: application/vnd.github.v3.full+json",
                "User-Agent: Retrofit-Sample-App"
        })
        @GET("users/{username}")
        Call<User> getUserS(@Path("username") String username);
    
        /**
         * 动态设置Header
         * @param authorization
         * @return
         */
        @GET("user")
        Call<User> getUser(@Header("Authorization") String authorization);
    
        @GET("user")
        Call<User> getUser(@HeaderMap Map<String, String> headers);
    
    }
    
    public static void retrofitDemo(String url) {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
        GitHubService service = retrofit.create(GitHubService.class);
        try {
            List<User> users = service.groupList(1001).execute().body();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    可以看到,Retrofit是一种更上层的封装,你可以设置不同的网络框架client,这里是OkHttpClient,设置baseUrl,之后会和interface类中的请求注解路由参数结合在一起构成整体的url,不用像OkHttpClient每次请求都要传入整个url,ConverterFactory可以根据想要解析的格式自由选择,通常我们使用的都是bean->json、json->bean,现在这部分工作我们可以交给Retrofit去做,其他的Converter还有:

    • Gson: com.squareup.retrofit2:converter-gson
    • Jackson: com.squareup.retrofit2:converter-jackson
    • Moshi: com.squareup.retrofit2:converter-moshi
    • Protobuf: com.squareup.retrofit2:converter-protobuf
    • Wire: com.squareup.retrofit2:converter-wire
    • Simple XML: com.squareup.retrofit2:converter-simplexml
    • JAXB: com.squareup.retrofit2:converter-jaxb
    • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

    通过Retrofit实例构造出调用service的实例,调用其方法获取Response数据,简单的调用背后是复杂又巧妙的抽象设计,下面跟着源码好好的学习一下它的原理。

  • 源码分析

    首先baseUrl就是个验证并将url解析成http或者https格式并保存成HttpUrl对象的方法,client方法将OkHttpClient绑定到Retrofit.Builder,addConverterFactory把第三方的解析库对象添加进一个List<Converter.Factory>类型的集合,build方法就是构建出Retrofit实例:

    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<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    
      // 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);
      converterFactories.addAll(platform.defaultConverterFactories());
    
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }
    

    可以看到,build里面还加入了容错默认处理。baseUrl不能为空,这是必须参数之一,callFactory默认OkHttpClient,这里还有个Executor需要设置,因为我们外面没有设置过这个,所以它是null,然后通过platform的defaultCallbackExecutor方法创建,platform是通过实例话Builder时通过Platform.get()得到的:

    private static final Platform PLATFORM = findPlatform();
    
    static Platform get() {
      return PLATFORM;
    }
    
    private static Platform findPlatform() {
      return "Dalvik".equals(System.getProperty("java.vm.name"))
          ? new Android() //
          : new Platform(true);
    }
    

    因为我们是android,所以这里是Dalvik虚拟机,因此是Android()作为platform,它的defaultCallbackExecutor如下:

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    
    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
    
      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
    

    所以这里使用MainThreadExecutor作为callbackExecutor,可以看到,Android回调操作通常都是和UI的交互,所以回调操作默认是要回到主线程操作的。

    再往下需要注意的是converterFactories除了添加我们外面传入的this.converterFactories之外还添加了一个BuiltInConverters和platform.defaultConverterFactories(),注意添加顺序,platform.defaultConverterFactories(),这个方法实现在Platform中:

    List<? extends Converter.Factory> defaultConverterFactories() {
      return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
    }
    

    hasJava8Types是在Platfrom构造方法中指定的,这里用的是Android(),所以hasJava8Types默认是false,所以这里defaultConverterFactories返回emptyList(),所以此时converterFactories里面有BuiltInConverters和我们设置的一个Converter(这里是GsonConverterFactory)。

    接下来就是调用create获取接口service对象,那interface是怎样可能创建对象呢?还有interface方法的注解是如何映射成最后发送的request的呢?继续往下看:

    @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
    public <T> T create(final Class<T> service) {
      //检查service是否符合要求
      validateServiceInterface(service);
      return (T)
          Proxy.newProxyInstance(
              service.getClassLoader(),
              new Class<?>[] {service},
              new InvocationHandler() {
                private final Platform platform = Platform.get();
                private final Object[] emptyArgs = new Object[0];
    
                @Override
                public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                    throws Throwable {
                  // If the method is a method from Object then defer to normal invocation.
                  if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                  }
                  args = args != null ? args : emptyArgs;
                  return platform.isDefaultMethod(method)
                      ? platform.invokeDefaultMethod(method, service, proxy, args)
                      : loadServiceMethod(method).invoke(args);
                }
              });
    }
    
    private void validateServiceInterface(Class<?> service) {
      //service必须是interface
      if (!service.isInterface()) {
        throw new IllegalArgumentException("API declarations must be interfaces.");
      }
      
      //使用双向队列保存service及其继承的其他interface,add是添加到队尾,然后从头部依次读取判断每个interface是否符合
      Deque<Class<?>> check = new ArrayDeque<>(1);
      check.add(service);
      while (!check.isEmpty()) {
        Class<?> candidate = check.removeFirst();
        //这里要求接口不能有泛型
        if (candidate.getTypeParameters().length != 0) {
          StringBuilder message =
              new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
          if (candidate != service) {
            message.append(" which is an interface of ").append(service.getName());
          }
          throw new IllegalArgumentException(message.toString());
        }
        Collections.addAll(check, candidate.getInterfaces());
      }
    
      //创建retrofit对象时传入的最后一个参数,表示是否提前执行loadServiceMethod方法
      if (validateEagerly) {
        Platform platform = Platform.get();
        for (Method method : service.getDeclaredMethods()) {
          //不能是default方法和静态方法。
          //根据isDefaultMethod的javadoc注释,default方法是非静态且有body的,这种方法在interface中存在必须需要default修饰符修饰且需要JDK1.8及以上。
          //interface中static修饰的方法需要有方法体
          if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
            loadServiceMethod(method);
          }
        }
      }
    }
    
    ServiceMethod<?> loadServiceMethod(Method method) {
      //之前的validateEagerly如果是true,那在create中调用loadServiceMethod的时候就直接从serviceMethodCache里面取,因为之前已经创建好了
      ServiceMethod<?> result = serviceMethodCache.get(method);
      if (result != null) return result;
    
      synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
          //创建ServiceMethod的地方
          result = ServiceMethod.parseAnnotations(this, method);
          serviceMethodCache.put(method, result);
        }
      }
      return result;
    }
    

    代码的作用我已经在注释中写明了,现在我们知道了实际上retrofit.create创建的是一个GithubService这个接口的动态代理,所以service.groupList实际上调用的动态代理的方法,至于动态代理的对象是怎么创建的,目前只能追溯到native方法,现在先不考虑JVM是怎么实例化代理对象的,我们只需要知道,当我们调用service.groupList的时候会回调到Proxy.newProxyInstance的最后一个参数new InvocationHandler()的invoke方法里,所以最终还是会调用loadServiceMethod方法,前面看到,loadServiceMethod方法创建的result返回对象在于ServiceMethod.parseAnnotations(this, method):

    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
      RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    
      //getGenericReturnType()会返回代码中书写的类型,比如说T method(){},则会返回T,而getReturnType会返回Object
      Type returnType = method.getGenericReturnType();
      //验证返回类型是否合法
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            method,
            "Method return type must not include a type variable or wildcard: %s",
            returnType);
      }
      //返回类型不能是void
      if (returnType == void.class) {
        throw methodError(method, "Service methods cannot return void.");
      }
    
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }
    
  
  这个方法首先通过RequestFactory.parseAnnotations创建了一个RequestFactory:
  
  ```java
  static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
    return new Builder(retrofit, method).build();
  }
Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();
  this.parameterTypes = method.getGenericParameterTypes();
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory build() {
  //解析作用于方法上的注解(做用于方法上的注解可以有多个,所以是循环解析)
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

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

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

  //解析作用于方法参数上的注解(注意parameterAnnotationsArray是一个二维数组,因为有多个参数,每个参数又可能拥有多个注解,但是只允许有一个注解)
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
    parameterHandlers[p] =
        parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
  }

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

  return new RequestFactory(this);
}

首先调用了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);
  } 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(method, "@Headers annotation is empty.");
    }
    headers = parseHeaders(headersToParse);
  } else if (annotation instanceof Multipart) {
    if (isFormEncoded) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isMultipart = true;
  } else if (annotation instanceof FormUrlEncoded) {
    if (isMultipart) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isFormEncoded = true;
  }
}

阅读代码可知,判断Annotation的类型,调用parseHttpMethodAndPath对应解析,注意只有PATCH、POST、PUT的hasBody参数传入的是true,不同的是Headers注解调用parseHeaders(),Multipart和FormUrlEncoded(表单)是互斥的,它俩分别结合PUT和POST使用,所以没有path。首先看一下parseHttpMethodAndPath方法:

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
  //不允许重复赋值
  if (this.httpMethod != null) {
    throw methodError(
        method,
        "Only one HTTP method is allowed. Found: %s and %s.",
        this.httpMethod,
        httpMethod);
  }
  this.httpMethod = httpMethod;
  this.hasBody = hasBody;
  //如果没有path则返回
  if (value.isEmpty()) {
    return;
  }

  // Get the relative URL path and existing query string, if present.
  int question = value.indexOf('?');
  if (question != -1 && question < value.length() - 1) {
    // Ensure the query string does not have any named parameters.
    //queryParams是?后面的内容
    String queryParams = value.substring(question + 1);
    //PARAM_URL_REGEX是\{XXX}\这种样式,不允许出现在?后面,需要使用@Query注解在方法参数里添加
    Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
    if (queryParamMatcher.find()) {
      throw methodError(
          method,
          "URL query string \"%s\" must not have replace block. "
              + "For dynamic query parameters use @Query.",
          queryParams);
    }
  }
  //比如/table?id=1,this.relativeUrl就是/table?id=1
  this.relativeUrl = value;
  this.relativeUrlParamNames = parsePathParameters(value);
}
static Set<String> parsePathParameters(String path) {
  Matcher m = PARAM_URL_REGEX.matcher(path);
  Set<String> patterns = new LinkedHashSet<>();
  while (m.find()) {
    patterns.add(m.group(1));
  }
  return patterns;
}

parsePathParameters会把?前面的\{paramName}\形式的参数名存到一个LinkedHashSet中,为什么是链式的,因为如果方法参数中没有指定参数名注解,则会按照顺序对应赋值。

parseHeaders就是根据“key:value”的形式去解析键值对,Content-Type需要通过MediaType解析:

private Headers parseHeaders(String[] headers) {
  Headers.Builder builder = new Headers.Builder();
  for (String header : headers) {
    int colon = header.indexOf(':');
    if (colon == -1 || colon == 0 || colon == header.length() - 1) {
      throw methodError(
          method, "@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
    }
    String headerName = header.substring(0, colon);
    String headerValue = header.substring(colon + 1).trim();
    if ("Content-Type".equalsIgnoreCase(headerName)) {
      try {
        contentType = MediaType.get(headerValue);
      } catch (IllegalArgumentException e) {
        throw methodError(method, e, "Malformed content type: %s", headerValue);
      }
    } else {
      builder.add(headerName, headerValue);
    }
  }
  return builder.build();
}

回到RequestFactory的build,parseParameter解析方法参数:

private @Nullable ParameterHandler<?> parseParameter(
    int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
  ParameterHandler<?> result = null;
  if (annotations != null) {
    for (Annotation annotation : annotations) {
      ParameterHandler<?> annotationAction =
          parseParameterAnnotation(p, parameterType, annotations, annotation);

      if (annotationAction == null) {
        continue;
      }

      if (result != null) {
        throw parameterError(
            method, p, "Multiple Retrofit annotations found, only one allowed.");
      }

      result = annotationAction;
    }
  }

  if (result == null) {
    if (allowContinuation) {
      try {
        if (Utils.getRawType(parameterType) == Continuation.class) {
          isKotlinSuspendFunction = true;
          return null;
        }
      } catch (NoClassDefFoundError ignored) {
      }
    }
    throw parameterError(method, p, "No Retrofit annotation found.");
  }

  return result;
}

parseParameterAnnotation的源码:

@Nullable
private ParameterHandler<?> parseParameterAnnotation(
    int p, Type type, Annotation[] annotations, Annotation annotation) {
  if (annotation instanceof Url) {
    validateResolvableType(p, type);
    if (gotUrl) {
      throw parameterError(method, p, "Multiple @Url method annotations found.");
    }
    if (gotPath) {
      throw parameterError(method, p, "@Path parameters may not be used with @Url.");
    }
    if (gotQuery) {
      throw parameterError(method, p, "A @Url parameter must not come after a @Query.");
    }
    if (gotQueryName) {
      throw parameterError(method, p, "A @Url parameter must not come after a @QueryName.");
    }
    if (gotQueryMap) {
      throw parameterError(method, p, "A @Url parameter must not come after a @QueryMap.");
    }
    if (relativeUrl != null) {
      throw parameterError(method, p, "@Url cannot be used with @%s URL", httpMethod);
    }

    gotUrl = true;

    if (type == HttpUrl.class
        || type == String.class
        || type == URI.class
        || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
      return new ParameterHandler.RelativeUrl(method, p);
    } else {
      throw parameterError(
          method,
          p,
          "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
    }

  } else if (annotation instanceof Path) {
    validateResolvableType(p, type);
    if (gotQuery) {
      throw parameterError(method, p, "A @Path parameter must not come after a @Query.");
    }
    if (gotQueryName) {
      throw parameterError(method, p, "A @Path parameter must not come after a @QueryName.");
    }
    if (gotQueryMap) {
      throw parameterError(method, p, "A @Path parameter must not come after a @QueryMap.");
    }
    if (gotUrl) {
      throw parameterError(method, p, "@Path parameters may not be used with @Url.");
    }
    if (relativeUrl == null) {
      throw parameterError(
          method, p, "@Path can only be used with relative url on @%s", httpMethod);
    }
    gotPath = true;

    Path path = (Path) annotation;
    String name = path.value();
    validatePathName(p, name);

    Converter<?, String> converter = retrofit.stringConverter(type, annotations);
    return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());

  } else if (annotation instanceof Query) {
    validateResolvableType(p, type);
    Query query = (Query) annotation;
    String name = query.value();
    boolean encoded = query.encoded();

    Class<?> rawParameterType = Utils.getRawType(type);
    gotQuery = true;
    if (Iterable.class.isAssignableFrom(rawParameterType)) {
      if (!(type instanceof ParameterizedType)) {
        throw parameterError(
            method,
            p,
            rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
      }
      ParameterizedType parameterizedType = (ParameterizedType) type;
      Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
      Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
      return new ParameterHandler.Query<>(name, converter, encoded).iterable();
    } else if (rawParameterType.isArray()) {
      Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
      Converter<?, String> converter =
          retrofit.stringConverter(arrayComponentType, annotations);
      return new ParameterHandler.Query<>(name, converter, encoded).array();
    } else {
      Converter<?, String> converter = retrofit.stringConverter(type, annotations);
      return new ParameterHandler.Query<>(name, converter, encoded);
    }

  } else if (annotation instanceof QueryName) {
    validateResolvableType(p, type);
    QueryName query = (QueryName) annotation;
    boolean encoded = query.encoded();

    Class<?> rawParameterType = Utils.getRawType(type);
    gotQueryName = true;
    if (Iterable.class.isAssignableFrom(rawParameterType)) {
      if (!(type instanceof ParameterizedType)) {
        throw parameterError(
            method,
            p,
            rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
      }
      ParameterizedType parameterizedType = (ParameterizedType) type;
      Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
      Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
      return new ParameterHandler.QueryName<>(converter, encoded).iterable();
    } else if (rawParameterType.isArray()) {
      Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
      Converter<?, String> converter =
          retrofit.stringConverter(arrayComponentType, annotations);
      return new ParameterHandler.QueryName<>(converter, encoded).array();
    } else {
      Converter<?, String> converter = retrofit.stringConverter(type, annotations);
      return new ParameterHandler.QueryName<>(converter, encoded);
    }

  } else if (annotation instanceof QueryMap) {
    validateResolvableType(p, type);
    Class<?> rawParameterType = Utils.getRawType(type);
    gotQueryMap = true;
    if (!Map.class.isAssignableFrom(rawParameterType)) {
      throw parameterError(method, p, "@QueryMap parameter type must be Map.");
    }
    Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
    if (!(mapType instanceof ParameterizedType)) {
      throw parameterError(
          method, p, "Map must include generic types (e.g., Map<String, String>)");
    }
    ParameterizedType parameterizedType = (ParameterizedType) mapType;
    Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
    if (String.class != keyType) {
      throw parameterError(method, p, "@QueryMap keys must be of type String: " + keyType);
    }
    Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
    Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);

    return new ParameterHandler.QueryMap<>(
        method, p, valueConverter, ((QueryMap) annotation).encoded());

  } else if (annotation instanceof Header) {
    validateResolvableType(p, type);
    Header header = (Header) annotation;
    String name = header.value();

    Class<?> rawParameterType = Utils.getRawType(type);
    if (Iterable.class.isAssignableFrom(rawParameterType)) {
      if (!(type instanceof ParameterizedType)) {
        throw parameterError(
            method,
            p,
            rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
      }
      ParameterizedType parameterizedType = (ParameterizedType) type;
      Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
      Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
      return new ParameterHandler.Header<>(name, converter).iterable();
    } else if (rawParameterType.isArray()) {
      Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
      Converter<?, String> converter =
          retrofit.stringConverter(arrayComponentType, annotations);
      return new ParameterHandler.Header<>(name, converter).array();
    } else {
      Converter<?, String> converter = retrofit.stringConverter(type, annotations);
      return new ParameterHandler.Header<>(name, converter);
    }

  } else if (annotation instanceof HeaderMap) {
    if (type == Headers.class) {
      return new ParameterHandler.Headers(method, p);
    }

    validateResolvableType(p, type);
    Class<?> rawParameterType = Utils.getRawType(type);
    if (!Map.class.isAssignableFrom(rawParameterType)) {
      throw parameterError(method, p, "@HeaderMap parameter type must be Map.");
    }
    Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
    if (!(mapType instanceof ParameterizedType)) {
      throw parameterError(
          method, p, "Map must include generic types (e.g., Map<String, String>)");
    }
    ParameterizedType parameterizedType = (ParameterizedType) mapType;
    Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
    if (String.class != keyType) {
      throw parameterError(method, p, "@HeaderMap keys must be of type String: " + keyType);
    }
    Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
    Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);

    return new ParameterHandler.HeaderMap<>(method, p, valueConverter);

  } else if (annotation instanceof Field) {
    validateResolvableType(p, type);
    if (!isFormEncoded) {
      throw parameterError(method, p, "@Field parameters can only be used with form encoding.");
    }
    Field field = (Field) annotation;
    String name = field.value();
    boolean encoded = field.encoded();

    gotField = true;

    Class<?> rawParameterType = Utils.getRawType(type);
    if (Iterable.class.isAssignableFrom(rawParameterType)) {
      if (!(type instanceof ParameterizedType)) {
        throw parameterError(
            method,
            p,
            rawParameterType.getSimpleName()
                + " must include generic type (e.g., "
                + rawParameterType.getSimpleName()
                + "<String>)");
      }
      ParameterizedType parameterizedType = (ParameterizedType) type;
      Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
      Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
      return new ParameterHandler.Field<>(name, converter, encoded).iterable();
    } else if (rawParameterType.isArray()) {
      Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
      Converter<?, String> converter =
          retrofit.stringConverter(arrayComponentType, annotations);
      return new ParameterHandler.Field<>(name, converter, encoded).array();
    } else {
      Converter<?, String> converter = retrofit.stringConverter(type, annotations);
      return new ParameterHandler.Field<>(name, converter, encoded);
    }

  } else if (annotation instanceof FieldMap) {
    validateResolvableType(p, type);
    if (!isFormEncoded) {
      throw parameterError(
          method, p, "@FieldMap parameters can only be used with form encoding.");
    }
    Class<?> rawParameterType = Utils.getRawType(type);
    if (!Map.class.isAssignableFrom(rawParameterType)) {
      throw parameterError(method, p, "@FieldMap parameter type must be Map.");
    }
    Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
    if (!(mapType instanceof ParameterizedType)) {
      throw parameterError(
          method, p, "Map must include generic types (e.g., Map<String, String>)");
    }
    ParameterizedType parameterizedType = (ParameterizedType) mapType;
    Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
    if (String.class != keyType) {
      throw parameterError(method, p, "@FieldMap keys must be of type String: " + keyType);
    }
    Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
    Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);

    gotField = true;
    return new ParameterHandler.FieldMap<>(
        method, p, valueConverter, ((FieldMap) annotation).encoded());

  } else if (annotation instanceof Part) {
    validateResolvableType(p, type);
    if (!isMultipart) {
      throw parameterError(
          method, p, "@Part parameters can only be used with multipart encoding.");
    }
    Part part = (Part) annotation;
    gotPart = true;

    String partName = part.value();
    Class<?> rawParameterType = Utils.getRawType(type);
    if (partName.isEmpty()) {
      if (Iterable.class.isAssignableFrom(rawParameterType)) {
        if (!(type instanceof ParameterizedType)) {
          throw parameterError(
              method,
              p,
              rawParameterType.getSimpleName()
                  + " must include generic type (e.g., "
                  + rawParameterType.getSimpleName()
                  + "<String>)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
        if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
          throw parameterError(
              method,
              p,
              "@Part annotation must supply a name or use MultipartBody.Part parameter type.");
        }
        return ParameterHandler.RawPart.INSTANCE.iterable();
      } else if (rawParameterType.isArray()) {
        Class<?> arrayComponentType = rawParameterType.getComponentType();
        if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
          throw parameterError(
              method,
              p,
              "@Part annotation must supply a name or use MultipartBody.Part parameter type.");
        }
        return ParameterHandler.RawPart.INSTANCE.array();
      } else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
        return ParameterHandler.RawPart.INSTANCE;
      } else {
        throw parameterError(
            method,
            p,
            "@Part annotation must supply a name or use MultipartBody.Part parameter type.");
      }
    } else {
      Headers headers =
          Headers.of(
              "Content-Disposition",
              "form-data; name=\"" + partName + "\"",
              "Content-Transfer-Encoding",
              part.encoding());

      if (Iterable.class.isAssignableFrom(rawParameterType)) {
        if (!(type instanceof ParameterizedType)) {
          throw parameterError(
              method,
              p,
              rawParameterType.getSimpleName()
                  + " must include generic type (e.g., "
                  + rawParameterType.getSimpleName()
                  + "<String>)");
        }
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
        if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
          throw parameterError(
              method,
              p,
              "@Part parameters using the MultipartBody.Part must not "
                  + "include a part name in the annotation.");
        }
        Converter<?, RequestBody> converter =
            retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);
        return new ParameterHandler.Part<>(method, p, headers, converter).iterable();
      } else if (rawParameterType.isArray()) {
        Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
        if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
          throw parameterError(
              method,
              p,
              "@Part parameters using the MultipartBody.Part must not "
                  + "include a part name in the annotation.");
        }
        Converter<?, RequestBody> converter =
            retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations);
        return new ParameterHandler.Part<>(method, p, headers, converter).array();
      } else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
        throw parameterError(
            method,
            p,
            "@Part parameters using the MultipartBody.Part must not "
                + "include a part name in the annotation.");
      } else {
        Converter<?, RequestBody> converter =
            retrofit.requestBodyConverter(type, annotations, methodAnnotations);
        return new ParameterHandler.Part<>(method, p, headers, converter);
      }
    }

  } else if (annotation instanceof PartMap) {
    validateResolvableType(p, type);
    if (!isMultipart) {
      throw parameterError(
          method, p, "@PartMap parameters can only be used with multipart encoding.");
    }
    gotPart = true;
    Class<?> rawParameterType = Utils.getRawType(type);
    if (!Map.class.isAssignableFrom(rawParameterType)) {
      throw parameterError(method, p, "@PartMap parameter type must be Map.");
    }
    Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
    if (!(mapType instanceof ParameterizedType)) {
      throw parameterError(
          method, p, "Map must include generic types (e.g., Map<String, String>)");
    }
    ParameterizedType parameterizedType = (ParameterizedType) mapType;

    Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
    if (String.class != keyType) {
      throw parameterError(method, p, "@PartMap keys must be of type String: " + keyType);
    }

    Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
    if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType))) {
      throw parameterError(
          method,
          p,
          "@PartMap values cannot be MultipartBody.Part. "
              + "Use @Part List<Part> or a different value type instead.");
    }

    Converter<?, RequestBody> valueConverter =
        retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);

    PartMap partMap = (PartMap) annotation;
    return new ParameterHandler.PartMap<>(method, p, valueConverter, partMap.encoding());

  } else if (annotation instanceof Body) {
    validateResolvableType(p, type);
    if (isFormEncoded || isMultipart) {
      throw parameterError(
          method, p, "@Body parameters cannot be used with form or multi-part encoding.");
    }
    if (gotBody) {
      throw parameterError(method, p, "Multiple @Body method annotations found.");
    }

    Converter<?, RequestBody> converter;
    try {
      converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
    } catch (RuntimeException e) {
      // Wide exception range because factories are user code.
      throw parameterError(method, e, p, "Unable to create @Body converter for %s", type);
    }
    gotBody = true;
    return new ParameterHandler.Body<>(method, p, converter);

  } else if (annotation instanceof Tag) {
    validateResolvableType(p, type);

    Class<?> tagType = Utils.getRawType(type);
    for (int i = p - 1; i >= 0; i--) {
      ParameterHandler<?> otherHandler = parameterHandlers[i];
      if (otherHandler instanceof ParameterHandler.Tag
          && ((ParameterHandler.Tag) otherHandler).cls.equals(tagType)) {
        throw parameterError(
            method,
            p,
            "@Tag type "
                + tagType.getName()
                + " is duplicate of parameter #"
                + (i + 1)
                + " and would always overwrite its value.");
      }
    }

    return new ParameterHandler.Tag<>(tagType);
  }

  return null; // Not a Retrofit annotation.
}

注意retrofit.requestBodyConverter是这里使用GsonConverter把bean转化成json的地方,怎么转换就交给GsonConverter了。至于Retrofit是在哪里用上的Converter转换请求参数的我们放在最后,现在还没走完请求流程不好理解。

类似于解析方法注解一样,针对Url、Path、Query、QueryName、QueryMap、Header、HeaderMap、Field、FieldMap、Part、PartMap、Body、Tag这些注解进行解析。

回到ServiceMethod的parseAnnotations方法,接下来会验证返回类型并最终会返回一个ServiceMethod,看一下Utils.hasUnresolvableType(returnType)方法:

static boolean hasUnresolvableType(@Nullable Type type) {
  if (type instanceof Class<?>) {
    return false;
  }
  //ParameterizedType,比如ArrayList<String>
  if (type instanceof ParameterizedType) {
    ParameterizedType parameterizedType = (ParameterizedType) type;
    //getActualTypeArguments()得到一个包含String的Type数组,递归调用会判断为Class类型
    for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
      if (hasUnresolvableType(typeArgument)) {
        return true;
      }
    }
    return false;
  }
  //GenericArrayType,比如T[]或T[][],
  if (type instanceof GenericArrayType) {
    //getGenericComponentType()会得到T和T[](脱一层数组)
    return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
  }
  //TypeVariable,比如T、E这种表示某种类型的
  if (type instanceof TypeVariable) {
    return true;
  }
  //WildcardType,? extends String这种通配符表示的,比如ArrayList<? extends String>这种ParameterType类型的调用parameterizedType.getActualTypeArguments()得到? extends String这种WildcardType类型
  if (type instanceof WildcardType) {
    return true;
  }
  String className = type == null ? "null" : type.getClass().getName();
  throw new IllegalArgumentException(
      "Expected a Class, ParameterizedType, or "
          + "GenericArrayType, but <"
          + type
          + "> is of type "
          + className);
}

返回类型验证没问题了就会通过parseAnnotations创建一个ServiceMethod,看看HttpServiceMethod.parseAnnotations做了什么:

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
    Retrofit retrofit, Method method, RequestFactory requestFactory) {
  boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
  boolean continuationWantsResponse = false;
  boolean continuationBodyNullable = false;

  Annotation[] annotations = method.getAnnotations();
  Type adapterType;
  if (isKotlinSuspendFunction) {
    Type[] parameterTypes = method.getGenericParameterTypes();
    Type responseType =
        Utils.getParameterLowerBound(
            0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
    if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
      // Unwrap the actual body type from Response<T>.
      responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
      continuationWantsResponse = true;
    } else {
      // TODO figure out if type is nullable or not
      // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
      // Find the entry for method
      // Determine if return type is nullable or not
    }

    adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
    annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
  } else {
    adapterType = method.getGenericReturnType();
  }

  CallAdapter<ResponseT, ReturnT> callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  Type responseType = callAdapter.responseType();
  if (responseType == okhttp3.Response.class) {
    throw methodError(
        method,
        "'"
            + getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
  }
  // TODO support Unit for Kotlin?
  if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
    throw methodError(method, "HEAD method must use Void as response type.");
  }

  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);

  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  if (!isKotlinSuspendFunction) {
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  } else if (continuationWantsResponse) {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>)
        new SuspendForResponse<>(
            requestFactory,
            callFactory,
            responseConverter,
            (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
  } else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>)
        new SuspendForBody<>(
            requestFactory,
            callFactory,
            responseConverter,
            (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
            continuationBodyNullable);
  }
}

通过createCallAdapter得到callAdapter:

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
    Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
  try {
    //noinspection unchecked
    return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(method, e, "Unable to create call adapter for %s", returnType);
  }
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
  return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(
    @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
  Objects.requireNonNull(returnType, "returnType == null");
  Objects.requireNonNull(annotations, "annotations == null");

  int start = callAdapterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter<?, ?> adapter = callAdapterFactories.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(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());
}

可以看到是从callAdapterFactories里面取的,还记得Retrofit.Builder的build的时候吗:

// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
    @Nullable Executor callbackExecutor) {
  DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
  return hasJava8Types
      ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
      : singletonList(executorFactory);
}

如果我们通过addCallAdapterFactory设置过CallAdapter则至少会有一个DefaultCallAdapterFactory,按照没设置的情况,callAdapterFactories.get(i).get(returnType, annotations, this)就会是:

@Override
public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  //必须是ParameterizedType类型
  if (!(returnType instanceof ParameterizedType)) {
    throw new IllegalArgumentException(
        "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
  }
  //getParameterUpperBound内部会通过getActualTypeArguments获取泛型类的类型,这里即是List
  final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

  final Executor executor =
      Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
          ? null
          : callbackExecutor;

  return new CallAdapter<Object, Call<?>>() {
    @Override
    public Type responseType() {
      return responseType;
    }

    @Override
    public Call<Object> adapt(Call<Object> call) {
      return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
    }
  };
}

同理,converter也一样会走到:

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
  Objects.requireNonNull(type, "type == null");
  Objects.requireNonNull(annotations, "annotations == null");

  int start = converterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter<ResponseBody, ?> converter =
        converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
      //noinspection unchecked
      return (Converter<ResponseBody, T>) converter;
    }
  }

先看构造Retrofit时第一个被添加的BuiltInConverters的responseBodyConverter:

@Override
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
    Type type, Annotation[] annotations, Retrofit retrofit) {
  if (type == ResponseBody.class) {
    return Utils.isAnnotationPresent(annotations, Streaming.class)
        ? StreamingResponseBodyConverter.INSTANCE
        : BufferingResponseBodyConverter.INSTANCE;
  }
  if (type == Void.class) {
    return VoidResponseBodyConverter.INSTANCE;
  }
  if (checkForKotlinUnit) {
    try {
      if (type == Unit.class) {
        return UnitResponseBodyConverter.INSTANCE;
      }
    } catch (NoClassDefFoundError ignored) {
      checkForKotlinUnit = false;
    }
  }
  return null;
}

可见这是泛型类没有明确指定时的容错处理。

我们这里addConverterFactory时传入了GsonConverterFactory.create(),所以去看看GsonConverterFactory的responseBodyConverter:

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

回到HttpServiceMethod的parseAnnotations,最终会返回一个CallAdapted(暂时不考虑kotlin协程的情况)。

然后就是调用动态代理中调用invoke方法,实际上就是HttpServiceMethod中的invoke方法:

@Override
final @Nullable ReturnT invoke(Object[] args) {
  Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
  return adapt(call, args);
}

也就是CallAdapted中的adapt方法:

 @Override
 protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
    return callAdapter.adapt(call);
 }

所以也就是DefaultCallAdapterFactory的get方法返回的CallAdapter的adapt:

@Override
public Call<Object> adapt(Call<Object> call) {
  return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}

到现在相当于service.groupList(1001)已经执行完了,接下来就是execute(),也就是这个ExecutorCallbackCall的execute方法:

@Override
public Response<T> execute() throws IOException {
  return delegate.execute();
}

delegate就是上面的OkHttpCall,它的execute是:

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

  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;

    call = getRawCall();
  }

  if (canceled) {
    call.cancel();
  }

  return parseResponse(call.execute());
}

getRawCall方法最终调用方法是:

private okhttp3.Call createRawCall() throws IOException {
  okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

这个callFactory经查找就是我们Retrofit.Builder().client()传入的OkHttpClient对象,所以这里的call.execute()就是OkHttpClient的newCall()的execute,再往下就是OkHttpClient的源码了。

至此,Retrofit的网络请求API调用过程就结束了。

那么response是怎么通过Converter解析的呢?还有个parseResponse方法:

Response<T> 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.
  rawResponse =
      rawResponse
          .newBuilder()
          .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
          .build();

  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
    try {
      // Buffer the entire body to avoid future I/O.
      ResponseBody bufferedBody = Utils.buffer(rawBody);
      return Response.error(bufferedBody, rawResponse);
    } finally {
      rawBody.close();
    }
  }

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

  ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
  try {
    T body = responseConverter.convert(catchingBody);
    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.
    catchingBody.throwIfCaught();
    throw e;
  }
}

responseConverter.convert(catchingBody)就是答案,responseConverter是前面的responseBodyConverter返回的GsonResponseBodyConverter:

@Override
public T convert(ResponseBody value) throws IOException {
  JsonReader jsonReader = gson.newJsonReader(value.charStream());
  try {
    T result = adapter.read(jsonReader);
    if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
      throw new JsonIOException("JSON document was not fully consumed.");
    }
    return result;
  } finally {
    value.close();
  }
}

下面就是Gson框架的部分了。

前面还有一点没讲就是Retrofit怎么引用这个converter解析request参数(即方法参数)的呢?

返回的ParameterHandler的子类会被保存到RequestFactory的parameterHandlers中,后面OkHttpCall调用createRawCall的时候有一句callFactory.newCall(requestFactory.create(args)),这个requestFactory.create中有一句handlers[p].apply(requestBuilder, args[p]),handlers就是parameterHandlers,所以这个apply就是ParameterHandler的相关子类中的apply方法,拿ParameterHandler.Body来说:

@Override
void apply(RequestBuilder builder, @Nullable T value) {
  if (value == null) {
    throw Utils.parameterError(method, p, "Body parameter value must not be null.");
  }
  RequestBody body;
  try {
    body = converter.convert(value);
  } catch (IOException e) {
    throw Utils.parameterError(method, e, p, "Unable to convert " + value + " to RequestBody");
  }
  builder.setBody(body);
}

converter.convert就调用到了前面设置的GsonRequestBodyConverter。

  • 总结

    通过源码深刻理解了从调用到解析,Retrofit是如何优雅的通过注解和动态代理的方式把OkHttpClient的调用封装起来,从而使得彼此之间地耦合度大大地降低地。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容