retrofit源码解析3--ServiceMethod

Retrofit.png

ServiceMethod是retrofit的核心之一。它的作用是将请求接口方法中的请求参数、请求方式等等,封装成java对象以供请求使用,所以它的重要性不言而喻。

final class ServiceMethod {
  // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
1 static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  final okhttp3.Call.Factory callFactory;
  final CallAdapter callAdapter;

  private final HttpUrl baseUrl;
  private final Converter responseConverter;
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
2 private final ParameterHandler[] parameterHandlers;


  public ServiceMethod build() {
3     callAdapter = createCallAdapter();
4     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?");
      }
5     responseConverter = createResponseConverter();

6     for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      '判断请求方法注解是否添加'
     ...
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

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

7       parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      '判断url、请求体等是否添加'
      ...
      return new ServiceMethod<>(this);
    }

  • 通过标记1到2之间的成员变量可以看出,ServiceMethod就是请求接口方法的一个包装类,它将请求方法转换成了一个java对象。
    methodAnnotations:请求的注解
    parameterTypes:参数类型
    parameterAnnotationsArray:参数的具体内容
    ...

  • 3:

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

通过返回类型和注解获取到对应的网络适配器,下面这段代码是此结论的具体实现:
(CallAdapter) retrofit.callAdapter(returnType, annotations)调用了Retrofit中的nextCallAdapter方法

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

    int start = adapterFactories.indexOf(skipPast) + 1;

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

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

从1中看到从RetrofitadapterFactories中取出我们设置的适配器并返回

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

创建retrofit时设置的rxjava适配器。上面createCallAdapter返回就是这个。

  • 5.createResponseConverter与createCallAdapter实现基本类似,不设置默认返回的是gson转换器
  • 6.遍历方法的注解,设置请求类型、请求头、请求格式等:
   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;
    }
  }
  • 7.解析方法参数

你可能感兴趣的:(retrofit源码解析3--ServiceMethod)