Android开源框架之Retrofit (二)

源码解析

Retrofit通过使用大量的设计模式进行功能模块的解耦。

Retrofit将各个功能模块进行了封装,只暴露了Retrofit核心类,只管配置Retrofit,然后做请求。剩下的事情就跟上层无关了,只需要等待回调,这就是外观模式的运用。

1、Retrofit实例是使用建造者模式通过内部Builder类进行创建的。
public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
      //添加一个默认的Converter
      converterFactories.add(new BuiltInConverters());
    }

    public Builder() {
      //Platform.get()获取支持的平台,Android
      this(Platform.get());
    }
    //这个一般不会用到
    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;
      converterFactories.addAll(retrofit.converterFactories);
      adapterFactories.addAll(retrofit.adapterFactories);
      // Remove the default, platform-aware call adapter added by build().
      adapterFactories.remove(adapterFactories.size() - 1);
      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }

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


    public Builder baseUrl(String baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      HttpUrl httpUrl = HttpUrl.parse(baseUrl);
      if (httpUrl == null) {
        throw new IllegalArgumentException("Illegal URL: " + baseUrl);
      }
      return baseUrl(httpUrl);
    }


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

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

    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

    public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = checkNotNull(executor, "executor == null");
      return this;
    }

    public Builder validateEagerly(boolean validateEagerly) {
      this.validateEagerly = validateEagerly;
      return this;
    }

    //这里可以看出baseUrl不能为空
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //判断callFactory是否为空,如果不设置为空的话就创建一个OkHttpClient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        //获取Android平台下的CallbackExecutor,返回的是MainThreadExecutor
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      //获取默认的CallAdapterFactory,返回的是ExecutorCallAdapterFactory
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

在创建Builder实例时调用的是Builder的无参构造放法,里面调用了Builder(Platform)这个构造方法,传入的是Platform.get()返回数据,这个方法是获取适配平台,返回Android。

可以通过Builder传入BaseUrl、callFactory、ConverterFactory、CallAdapterFactory等等。

调用build方法中主要是为了进行判断,设置默认的信息。最后创建一个Rretrofit对象返回。

Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
  List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
  Executor callbackExecutor, boolean validateEagerly) {
    //将Builder中传入的对象存储到对应的变量中
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = unmodifiableList(converterFactories); 
    this.adapterFactories = unmodifiableList(adapterFactories);
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
}

Retrofit对象创建完毕后,然后调用create方法生成接口实例对象。

2、create方法

create方法中使用的是动态代理的形式去生成实例接口对象。

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //使用动态代理模式获取实例对象
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },new InvocationHandler() {
          private final Platform platform = Platform.get();
          @Override 
          public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {                    
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
}

在上面的使用中Dream dream = retrofit.create(Dream.class);就是使用Proxy动态代理生成Dream接口对象。在调用接口中的方法dream.get(“吃饭”, “e136460f8f0bf18f431bdb7848267fbc”);就会调用invoke方法。invoke方法中method和args就是对应接口中的方法和参数。

然后调用loadServiceMethod将方法进行解析并封装成ServiceMethod。

loadServiceMethod方法

ServiceMethod<?, ?> loadServiceMethod(Method method) {
    //从缓存中获取ServiceMethod对象
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    //不为空就将ServiceMethod对象返回
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
      为空的话就去创建一个新的ServiceMethod对象。使用的也是Builder建造者模式。
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
}

serviceMethodCache是一个map的缓存变量,以method为key,ServiceMethod为value。

接下来看一下ServiceMethod的创建:

Builder(Retrofit retrofit, Method method) {
   this.retrofit = retrofit;
   this.method = method;
   this.methodAnnotations = method.getAnnotations();
   this.parameterTypes = method.getGenericParameterTypes();
   this.parameterAnnotationsArray = method.getParameterAnnotations();
}

保存retrofit、method变量对象,从method中获取方法的所有注解、所有参数类型、参数注解数组。

//@GET("/dream/query")
//Call get(@Query(“q”) String q,@Query(“key”) String key);

注:参数注解数组是二维数组[][]

然后看一下build方法:

public ServiceMethod build() {
    //创建CallAdapter
    callAdapter = createCallAdapter();
	//获取响应类型
    responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError("'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
	//创建Converter
    responseConverter = createResponseConverter();
    //循环方法的注解
    for (Annotation annotation : methodAnnotations) {
      parseMethodAnnotation(annotation);
    }

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

    if (!hasBody) {
      if (isMultipart) {
        throw methodError(
            "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
      }
      if (isFormEncoded) {
        throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
            + "request body (e.g., @POST).");
      }
    }
    //参数的个数,参数注解是二位数组
    int parameterCount = parameterAnnotationsArray.length;
	//创建一个存放参数信息的对象parameterHandlers数组
    parameterHandlers = new ParameterHandler<?>[parameterCount];
	//循环参数个数
    for (int p = 0; p < parameterCount; p++) {
	  //获取一个参数的类型
      Type parameterType = parameterTypes[p];
      if (Utils.hasUnresolvableType(parameterType)) {
        throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
            parameterType);
      }
      //从参数注解数组中拿到其中一个参数的注解信息
      Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
      if (parameterAnnotations == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }
      //解析并将参数的信息封装成parameterHandler并放到数组中
      parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
    }

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

    return new ServiceMethod<>(this);
}

build方法中看到CallAdapter和Converter会在后面进行讲解。接下来就会看到主要就是将方法中的注解以及参数进行解析封装。然后返回一个ServiceMethod对象。一步一步分析看一下。先是解析方法中的注解。

----parseMethodAnnotation—解析方法中的注解

private void parseMethodAnnotation(Annotation annotation) {
    if (annotation instanceof DELETE) {
      parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
    } else if (annotation instanceof GET) {
      parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
    } else if (annotation instanceof HEAD) {
      parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
      if (!Void.class.equals(responseType)) {
        throw methodError("HEAD method must use Void as response type.");
      }
    } else if (annotation instanceof PATCH) {
      parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
    } else if (annotation instanceof POST) {
      parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
    } else if (annotation instanceof PUT) {
      parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
    } else if (annotation instanceof OPTIONS) {
      parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
    } else if (annotation instanceof HTTP) {
      HTTP http = (HTTP) annotation;
      parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
    } else if (annotation instanceof retrofit2.http.Headers) {
      String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
      if (headersToParse.length == 0) {
        throw methodError("@Headers annotation is empty.");
      }
      headers = parseHeaders(headersToParse);
    } else if (annotation instanceof Multipart) {
      if (isFormEncoded) {
        throw methodError("Only one encoding annotation is allowed.");
      }
      isMultipart = true;
    } else if (annotation instanceof FormUrlEncoded) {
      if (isMultipart) {
        throw methodError("Only one encoding annotation is allowed.");
      }
      isFormEncoded = true;
    }
}

这个方法就看起来比较熟悉了,就是判断注解的实体类。在上面使用的中用到了GET请求,主要看一下GET的分支,其他的都是一样的。

GET中调用了parseHttpMethodAndPath(“GET”, ((GET) annotation).value(), false);

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('?');
    if (question != -1 && question < value.length() - 1) {
      // Ensure the query string does not have any named parameters.
      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);
      }
    }
    //注解值
    this.relativeUrl = value;
	//使用正则检验value
    this.relativeUrlParamNames = parsePathParameters(value);
}

将请求方法和注解的值保存到变量中。比如上面的使用@GET("/dream/query"),请求的方法是get请求httpMethod是get,relativeUrl 是"/dream/query"。至此方法注解就解析完了,拿到注解中的信息。

接下啦就是循环所有的参数个数解析每个参数中的注解信息,调用parseParameter方法。

----parseParameter—解析参数中的注解

private ParameterHandler<?> parseParameter(int p, Type parameterType, Annotation[] annotations) {
    ParameterHandler<?> result = null;
	//循环一个参数中的注解
    for (Annotation annotation : annotations) {
      //解析参数注解并将其封装成ParameterHandler
	  ParameterHandler<?> annotationAction = parseParameterAnnotation(
          p, parameterType, annotations, annotation);
       
      if (annotationAction == null) {
        continue;
      }

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

    if (result == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }
	//将获取的ParameterHandler对象返回
    return result;
}

----parseParameterAnnotation—解析参数中的注解

private ParameterHandler<?> parseParameterAnnotation(int p, Type type, Annotation[] annotations, Annotation annotation) {
    
	if (annotation instanceof Url) {
      if (gotUrl) {
        throw parameterError(p, "Multiple @Url method annotations found.");
      }
      if (gotPath) {
        throw parameterError(p, "@Path parameters may not be used with @Url.");
      }
      if (gotQuery) {
        throw parameterError(p, "A @Url parameter must not come after a @Query");
      }
      if (relativeUrl != null) {
        throw parameterError(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();
      } else {
        throw parameterError(p,
            "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
      }

    } else if (annotation instanceof Path) {
      if (gotQuery) {
        throw parameterError(p, "A @Path parameter must not come after a @Query.");
      }
      if (gotUrl) {
        throw parameterError(p, "@Path parameters may not be used with @Url.");
      }
      if (relativeUrl == null) {
        throw parameterError(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<>(name, converter, path.encoded());

    } else if (annotation instanceof Query) {
      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(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) {
      QueryName query = (QueryName) annotation;
      boolean encoded = query.encoded();

      Class<?> rawParameterType = Utils.getRawType(type);
      gotQuery = true;
      if (Iterable.class.isAssignableFrom(rawParameterType)) {
        if (!(type instanceof ParameterizedType)) {
          throw parameterError(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) {
      Class<?> rawParameterType = Utils.getRawType(type);
      if (!Map.class.isAssignableFrom(rawParameterType)) {
        throw parameterError(p, "@QueryMap parameter type must be Map.");
      }
      Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
      if (!(mapType instanceof ParameterizedType)) {
        throw parameterError(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(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<>(valueConverter, ((QueryMap) annotation).encoded());

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

      Class<?> rawParameterType = Utils.getRawType(type);
      if (Iterable.class.isAssignableFrom(rawParameterType)) {
        if (!(type instanceof ParameterizedType)) {
          throw parameterError(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) {
      Class<?> rawParameterType = Utils.getRawType(type);
      if (!Map.class.isAssignableFrom(rawParameterType)) {
        throw parameterError(p, "@HeaderMap parameter type must be Map.");
      }
      Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
      if (!(mapType instanceof ParameterizedType)) {
        throw parameterError(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(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<>(valueConverter);

    } else if (annotation instanceof Field) {
      if (!isFormEncoded) {
        throw parameterError(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(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) {
      if (!isFormEncoded) {
        throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
      }
      Class<?> rawParameterType = Utils.getRawType(type);
      if (!Map.class.isAssignableFrom(rawParameterType)) {
        throw parameterError(p, "@FieldMap parameter type must be Map.");
      }
      Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
      if (!(mapType instanceof ParameterizedType)) {
        throw parameterError(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(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<>(valueConverter, ((FieldMap) annotation).encoded());

    } else if (annotation instanceof Part) {
      if (!isMultipart) {
        throw parameterError(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(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(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(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(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(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(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<>(headers, converter).iterable();
        } else if (rawParameterType.isArray()) {
          Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
          if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
            throw parameterError(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<>(headers, converter).array();
        } else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
          throw parameterError(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<>(headers, converter);
        }
      }

    } else if (annotation instanceof PartMap) {
      if (!isMultipart) {
        throw parameterError(p, "@PartMap parameters can only be used with multipart encoding.");
      }
      gotPart = true;
      Class<?> rawParameterType = Utils.getRawType(type);
      if (!Map.class.isAssignableFrom(rawParameterType)) {
        throw parameterError(p, "@PartMap parameter type must be Map.");
      }
      Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
      if (!(mapType instanceof ParameterizedType)) {
        throw parameterError(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(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(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<>(valueConverter, partMap.encoding());

    } else if (annotation instanceof Body) {
      if (isFormEncoded || isMultipart) {
        throw parameterError(p,
            "@Body parameters cannot be used with form or multi-part encoding.");
      }
      if (gotBody) {
        throw parameterError(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(e, p, "Unable to create @Body converter for %s", type);
      }
      gotBody = true;
      return new ParameterHandler.Body<>(converter);
    }

    return null; // Not a Retrofit annotation.
}

这个方法比较多,但内容其实都是一样的。主要是通过不同的参数注解,生成ParameterHandler对象。

比如上面测试用的:Call get(@Query(“q”) String q,@Query(“key”) String key);

下面就以这个方法中的第一个参数的来进行解析“@Query(“q”) String q”来对这个方法进行解析。

首先判断注解是Query,那么就进入Query这个分支中去看一下:

Query query = (Query) annotation;
//获取注解的值,也就是"q"
String name = query.value();
//获取编码,默认是false
boolean encoded = query.encoded();
//获取参数的类型的Class对象,也就是String
Class<?> rawParameterType = Utils.getRawType(type);
gotQuery = true;
//判断参数类型是否Iterable迭代器类型或子类
if (Iterable.class.isAssignableFrom(rawParameterType)) {
  if (!(type instanceof ParameterizedType)) {
    throw parameterError(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);
}

最终会将参数的注解信息封装ParameterHandler类型的对象。ParameterHandler是一个抽象类,有一个apply的抽象方法。Query是继承ParameterHandler的子类。

static final class Query<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;
    //构造方法
    Query(String name, Converter<T, String> valueConverter, boolean encoded) {
      //注解的值
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }
    //继承实现ParameterHandler的apply方法
    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) return; // Skip null values.

      String queryValue = valueConverter.convert(value);
      if (queryValue == null) return; // Skip converted but null values

      builder.addQueryParam(name, queryValue, encoded);
    }
}

这样整个ServiceMethod中Builder的build方法就完成了,主要就是将方法中的注解以及参数的注解进行封装。

回到ServiceMethod中Builder.build()方法,最后会创建一个serviceMethod对象。

new ServiceMethod<>(this)

ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
}

将Builder中的解析的数据保存到变量中。创建完ServiceMethod对象后,回到Retrofit的create方法中。接下来就会去创建OkHttpCall。

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

OkHttpCall继承了Call对象。

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

OkHttpCall创建完成后,然后调用serviceMethod.callAdapter.adapt()方法返回一个Call。

return serviceMethod.callAdapter.adapt(okHttpCall);

这里先不对callAdapter先不具体分析,在Retrofit进行Builder的时候会去获取所在的平台,这里是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);
      }
    }
}

defaultCallAdapterFactory是默认创建一个CallAdapterFactory,进入ExecutorCallAdapterFactory中可以看到:

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

这个方法中的参数call传过来的okHttpCall,ExecutorCallbackCall也是继承了Call对象。这样在默认的情况下return serviceMethod.callAdapter.adapt(okHttpCall);就是将Call对象返回。

//Call call = dream.get(Q, KEY);
//Response response = call.execute();

然后调用call.execute()时在ExecutorCallbackCall的execute方法中直接去调用OkHttpCall的execute方法,进入OkHttpCall.execute()方法中看一下:

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

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

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else {
          throw (RuntimeException) creationFailure;
        }
      }
      
      call = rawCall;
      if (call == null) {
        try {
		  //调用createRawCall方法创建一个okhttp3.Call
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    //解析返回值
    return parseResponse(call.execute());
}

这个方法前面就是一个判断,直接看createRawCall()去创建okhttp3.Call

private okhttp3.Call createRawCall() throws IOException {
    //创建Request对象
    Request request = serviceMethod.toRequest(args);
	//调用okhttp3发送请求
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
}

进入serviceMethod.toRequest去看一下如何创建Request对象:

Request toRequest(@Nullable Object... args) throws IOException {
    //创建RequestBuilder对象
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);
    
    @SuppressWarnings("unchecked")
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    
    int argumentCount = args != null ? args.length : 0;
	//判断参数值与参数注解数组的长度是否一致
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }
    //循环参数注解信息数组
    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
}

参数args就是调用方法时传递的值。

首先创建了一个RequestBuilder对象,将解析出来的httpMethod、relativeUrl等等信息传递过去。

然后将创建serviceMethod时得到的参数注解信息的数组parameterHandlers循环,调用apply方法。

在之前的分析中由于测试时参数的注解是Query,得到一个继承ParameterHandler的Query子类。

//继承实现ParameterHandler的apply方法
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
    if (value == null) return; // Skip null values.

        String queryValue = valueConverter.convert(value);
        if (queryValue == null) return; // Skip converted but null values

        builder.addQueryParam(name, queryValue, encoded);
}

在apply方法中调用RequestBuilder的addQueryParam方法将参数的注解值name、参数的值queryValue等信息传递过去。

进入addQueryParam方法:

void addQueryParam(String name, @Nullable String value, boolean encoded) {
    if (relativeUrl != null) {
      // Do a one-time combination of the built relative URL and the base URL.
      urlBuilder = baseUrl.newBuilder(relativeUrl);
      if (urlBuilder == null) {
        throw new IllegalArgumentException(
            "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
      }
      relativeUrl = null;
    }

    if (encoded) {
      //noinspection ConstantConditions Checked to be non-null by above 'if' block.
      urlBuilder.addEncodedQueryParameter(name, value);
    } else {
      //noinspection ConstantConditions Checked to be non-null by above 'if' block.
      urlBuilder.addQueryParameter(name, value);
    }
}

这个方法就主要的功能就是将请求URL完整拼接起来。

接下来就会去调用build方法去创建Request对象

Request build() {
    HttpUrl url;
    HttpUrl.Builder urlBuilder = this.urlBuilder;
	//生成HttpUrl对象
    if (urlBuilder != null) {
      url = urlBuilder.build();
    } else {
      url = baseUrl.resolve(relativeUrl);
      if (url == null) {
        throw new IllegalArgumentException(
            "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
      }
    }
    //获取RequestBody
    RequestBody body = this.body;
    if (body == null) {
      // Try to pull from one of the builders.
      if (formBuilder != null) {
        body = formBuilder.build();
      } else if (multipartBuilder != null) {
        body = multipartBuilder.build();
      } else if (hasBody) {
        // Body is absent, make an empty body.
        body = RequestBody.create(null, new byte[0]);
      }
    }
    //获取MediaType
    MediaType contentType = this.contentType;
    if (contentType != null) {
      if (body != null) {
        body = new ContentTypeOverridingRequestBody(body, contentType);
      } else {
        requestBuilder.addHeader("Content-Type", contentType.toString());
      }
    }
    //生成Request对象
    return requestBuilder
        .url(url)
        .method(method, body)
        .build();
}

这个方法就是使用requestBuilder的build方法生成一个okhttp3.Request对象

再次回到createRawCall方法,生成Request对象后就会去使用okhttp3发送请求

//调用okhttp3发送请求
okhttp3.Call call = serviceMethod.callFactory.newCall(request);

执行网络请求,请求完成后,获取到响应,解析响应数据。

parseResponse(call.execute());

将数据返回。这样整个Retrofit的源码就解析完了。

上面Retrofit的解析是在默认的情况下进行的,Retrofit还可以配置一些自定义,比如OkHttpClient、GsonConverterFactory、RxJava2CallAdapterFactory等等。

ConverterFactory和CallAdapterFactory在上面没有具体的解析,接下来分析一下。

在创建Retrofit的Builder的时候,可以通过addConverterFactory和addCallAdapterFactory方法来添加ConverterFactory与CallAdapterFactory,如果没有添加就使用默认的。

Retrofit提供了BuiltInConverters和ExecutorCallAdapterFactory默认的类。

在Builder.build方法中将其分别添加到List集合中

private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();

先来看一下测试中的代码

Call<ResponseBody> get(@Query("q") String q,@Query("key") String key);

返回了一个Call对象。可以看到返回值分为两部分:

一部分是前面的Call,也可以是Observable(如果使用RxJava就是Observable)。
	
另一部分是ResponseBody,也可以是其他的类型比如String、int、实体类等等。

其中:

addCallAdapterFactory影响的就是第一部分的Call(默认)或者Observable(RxJava)

addConverterFactory影响的就是第二部分以及我们的请求参数

接下来看内部是如何做的。

在上面Retrofit解析生成ServiceMethod对象的Builder的build()中

public ServiceMethod build() {
    //创建CallAdapter
    callAdapter = createCallAdapter();
	//获取响应类型
    responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError("'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
	//创建Converter
    responseConverter = createResponseConverter();
    
	......

    return new ServiceMethod<>(this);
}

获取了callAdapter和responseConverter实例,并且拿到返回值的类型。

先来看一下callAdapter

private CallAdapter<T, R> createCallAdapter() {
    //获取方法的返回值类型 比如测试中就是:Call<ResponseBody>
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
	//返回值不能是void
    if (returnType == void.class) {
      throw methodError("Service methods cannot return void.");
    }
    Annotation[] annotations = method.getAnnotations();
    try {
      //调用retrofit.callAdapter生成一个CallAdapter
      return (CallAdapter<T, R>) 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方法去生成CallAdapter

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    //调用nextCallAdapter方法
	return nextCallAdapter(null, returnType, annotations);
}

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
    Annotation[] annotations) {
	//非空判断
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
    //去除adapterFactories集合中的null值,由于retrofit默认添加一个ExecutorCallAdapterFactory,所以start=0
    int start = adapterFactories.indexOf(skipPast) + 1;
	//循环adapterFactories集合
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
	  //调用get方法获取CallAdapter对象
      CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      //如果adapter不为null就返回
	  if (adapter != null) {
        return adapter;
      }
    }
    //如果没有找到匹配的CallAdapterFactory就throw一个Exception
    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
}

通过查看这个nextCallAdapter方法,需要去继承CallAdapter.Factory的子类的get方法中去看一下,默认是ExecutorCallAdapterFactory,通过上面的分析知道ExecutorCallAdapterFactory是在创建Platform的Android类的时候创建的。进去看一下。

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //判断返回值类型是否Call对象,不是就返回null
	if (getRawType(returnType) != Call.class) {
      return null;
    }
	//获取返回值类型,比如Call<ResponseBody>中的ResponseBody对象
    final Type responseType = Utils.getCallResponseType(returnType);
    
	return new CallAdapter<Object, Call<?>>() {
      //将获取的返回值类型返回
	  @Override public Type responseType() {
        return responseType;
      }
      //adpter方法生成ExecutorCallbackCall对象
      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
}

这个方法可以看到ExecutorCallAdapterFactory支持的是返回类型是Call的请求,如果返回值是Observable,那么就会返回一个null,这时就需要配置RxJava2CallAdapterFactory。

Utils.getCallResponseType方法是用来获取Call中的泛型T

接下来就又回到上面Retrofit的解析,return serviceMethod.callAdapter.adapt(okHttpCall);调用adapt方法去完成请求。

接下来看一下获取到的Call中的泛型T的用处。

public ServiceMethod build() {
    //创建CallAdapter
    callAdapter = createCallAdapter();
	//获取响应类型
    responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw methodError("'"
          + Utils.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
	//创建Converter
    responseConverter = createResponseConverter();
    
	......

    return new ServiceMethod<>(this);
}

在ServiceMethod对象的Builder的build()中获取完callAdapter后,拿到responseType后,就会去获取Converter对象。

进入到createResponseConverter方法

private Converter<ResponseBody, T> createResponseConverter() {
    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.responseBodyConverter方法中去获取Converter对象

public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    //调用nextResponseBodyConverter方法
	return nextResponseBodyConverter(null, type, annotations);
}

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    //非空判断
	checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");
    //去除converterFactories集合中的null值,由于retrofit默认添加一个BuiltInConverters,所以start=0
    int start = converterFactories.indexOf(skipPast) + 1;
    //循环converterFactories集合
	for (int i = start, count = converterFactories.size(); i < count; i++) {
      获取Converter对象
	  Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      //如果adapter不为null就返回
	  if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
    //如果没有找到匹配的Converter就throw一个Exception
    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());
}

从上面代码中可以看出Converter对象的创建和CallAdapter对象的创建相似。需要去继承Converter.Factory的子类的responseBodyConverter方法中去看一下。

默认有一个BuiltInConverters,进入看一下

@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
    //判断响应类型是不是ResponseBody类型
    if (type == ResponseBody.class) {
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
	//判断响应类型是不是Void类型
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
}

从这个方法中可以知道默认的BuiltInConverters可以处理响应类型是ResponseBody和Void的请求,如果是其他的返回类型,比如String、int、实体类等等就需要使用其他的Converter。比如GsonConverterFactory、ScalarsConverterFactory、自定义一个Converter等等。

简单看一下BuiltInConverters中的具体做法,比如StreamingResponseBodyConverter

static final class StreamingResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      return value;
    }
}

Converter是一个接口,只有一个convert方法。StreamingResponseBodyConverter直接将ResponseBody不处理返回。

convert方法的调用是在解析网络请求的返回值的时候会调用。

parseResponse(call.execute());

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();           
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();
    //判断响应的code
    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);
    }
     
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
	  //解析响应的数据
      T body = serviceMethod.toResponse(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;
    }
}

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
}

在这个方法中就可以看到responseConverter.convert方法。适配器和工厂模式

这样ConverterFactory和CallAdapterFactory就介绍完了。主要都是通过返回值类型去判断需要使用哪一个Converter或CallAdapter。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值