Retrofi分析(二)

接着上一篇Retrofi分析(一)继续分析

下面开始分析创建Retrofit对象和service 对象 这一部分是Retrofit框架的核心部分

Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())//设置数据解析器
                .baseUrl("https://api.github.com/")//设置请求的URL地址
                .build();
GitHubService service = retrofit.create(GitHubService.class);

可以看到 Retrofit 本身是通过构建者模式实现 进入Retrofit 里面 首先看到Retrofit 的一些成员变量,先看看这些成员变量是干什么用的。

public final class Retrofit {
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;
......省略后面代码

因为它是通过builder模式构建的所以builder中的代码也需要看

 Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;

      converterFactories.addAll(retrofit.converterFactories);
      // Remove the default BuiltInConverters instance added by build().
      converterFactories.remove(0);

      callAdapterFactories.addAll(retrofit.callAdapterFactories);
      // Remove the default, platform-aware call adapter added by build().
      callAdapterFactories.remove(callAdapterFactories.size() - 1);

      callbackExecutor = retrofit.callbackExecutor;
      validateEagerly = retrofit.validateEagerly;
    }

serviceMethodCache :是一个ConcurrentHashMap,主要用于缓存服务方法。以前版本使用的是LinkedHashMap,ConcurrentHashMap是线程安全的。ServiceMethod就是通过上一篇中的注解生成的方法类。

callFactory:在build方法中可以看到if (callFactory == null) {callFactory = new OkHttpClient();} 这个callFactory其实就是我们okhttp中的 核心类OkHttpClient对象。

baseUrl:基地址,通过它和我们自定义的service中定义的相对地址可以拼接出来完整的url请求地址

converterFactories:数据转换器工厂的集合。用来把我们响应回来的数据封装成我们需要的序列化对象。比如上面例子中用到的GsonConverterFactory.addConverterFactory(GsonConverterFactory.create())。就是把返回的json对象转化成指定的java对象。
官方已经给我们提供了很多种解析工厂,我们自己也可以继承Converter.Factory自己实现。
官方提供的:
这里写图片描述
看一下GsonConverterFactory的源码

public final class GsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

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

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

构造方法是private 的不能new,有两个创建方法,create()和create(Gson gson)。内部有一个final的Gson类型的变量gson,在构造GsonConverterFactory被初始化

它两个public方法responseBodyConverter和requestBodyConverter,都是通过gson.getAdapter方法获取TypeAdapter(类型适配器)对象,在把这个TypeAdapter(类型适配器)对象作为构造函数的参数传入GsonResponseBodyConverter和GsonRequestBodyConverter中。其内部就是通过gson库来解析json的逻辑了

callAdapterFactories: call的适配器工厂集合。把call对象转换成其他平台的call对象,默认使用的ExecutorCallAdapterFactory。

如果我们在创建的时候配置了比如使用Rxjava和Retrofit配合,就可以吧Retrofit中的Call对象转换成Rxjava中的Observable对象返回。.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

如果跟RxJava结合开发,官方已经给我们定义好了一个类RxJava2CallAdapterFactory,RxJava2CallAdapterFactory这个类继承了CallAdapter.Factory,而CallAdapter.Factory是接口CallAdapter中的一个抽象类。我们自己也可以继承CallAdapter.Factory来实现自己的适配器类。所以主要看一下CallAdapter这个接口

public interface CallAdapter<R, T> {

  Type responseType();

  T adapt(Call<R> call);


  abstract class Factory {

    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);


    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }

第一个方法:Type responseType(); ,响应返回类型,比如我们的上一篇GitHubService中定义的Call<List<Repo>> listRepos(@Path("user") String user);这个返回类型就是List<Repo>>
第二个方法:T adapt(Call call);,T就是我们的Retrofit的Call适配成别的平台的返回的实例。比如RxJava中的Observable对象。
第三个工厂类中的 CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);返回一个CallAdapter的实例,如果工厂无法处理则返回null
第四个工厂类中的 Type getParameterUpperBound(int index, ParameterizedType type)返回index参数的上限
第五个工厂类中的 protected static Class<?> getRawType(Type type) 获取原始的类型例如:List<? extends Runnable> 则返回List.class

callbackExecutor: 回调执行器,主要用来处理异步的网络请求中到主线程的回调

validateEagerly:是否立即解析接口中的方法,默认是false。如果为true,程序是在做一个预处理的操作,只是提前创建了一些MethodHandler对象在缓存中。

platform: 适配的平台,Android,Java8。它有两个静态内部类分别对应着Android,Java8。下面看一下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);
      }
    }
  }

如果判断是Android平台会返回上面的这个对象。defaultCallAdapterFactory是默认的请求适配器工厂,MainThreadExecutor 静态内部类,通过new Handler(Looper.getMainLooper())来获取一个主线程的Handler。然后在执行主线程的时候,调用的是主线程的handler的post方法。我们知道Android中操作UI界面需要在主线程中执行,MainThreadExecutor 就是一个主线程中的执行器


看完Retrofit对象的创建,就到了下面的一个非常重要的方法了retrofit.create方法,通过这个方法来获取GitHubService 的一个实例

GitHubService service = retrofit.create(GitHubService.class);

GitHubService 就是我们前面定义的接口。

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
    }

然后看retrofit.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 the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

首先看一下一个判断,如果我们设置validateEagerly为立即执行,validateEagerly在我们创建Retrofit的时候就创建好了。那么就会执行下面的方法eagerlyValidateMethods(service);

  private void eagerlyValidateMethods(Class<?> service) {
   //获取平台对象,安卓对象是Platform.Android
    Platform platform = Platform.get();
    //获取service类的所有方法,然后遍历它的所有方法
    for (Method method : service.getDeclaredMethods()) {
      //由于Platform.Android没有实现isDefaultMethod方法,所以默认返回false,下面的方法肯定执行
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }
boolean isDefaultMethod(Method method) {
    return false;
  }

这个方法通过反射,找到我们GitHubService中的所有的方法,然后遍历执行 loadServiceMethod(method);方法。由于isDefaultMethod方法永远返回false,说以每个方法都能执行到 loadServiceMethod(method);

ServiceMethod<?, ?> loadServiceMethod(Method method) {
     //先从缓冲中取出
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    //如果缓存中有,直接取出
    if (result != null) return result;
   //如果缓存中没有,加上同步锁
    synchronized (serviceMethodCache) {
      //加上锁后,为了保证实时性,再去取一次
      result = serviceMethodCache.get(method);
      if (result == null) {
      //如果还没有,直接构建一个ServiceMethod.Builder对象,
      //然后调用ServiceMethod.Builder的builer方法构建一个ServiceMethod
        result = new ServiceMethod.Builder<>(this, method).build();
        //把这个ServiceMethod 对象放入缓存中
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

serviceMethodCache,我们上面创建Retrofit的时候就已经创建了是一个ConcurrentHashMap。用来缓存ServiceMethod,由于反射比较消耗性能,所以为了避免这种性能消耗,我们保证同一个接口(api)的同一个方法,只会创建一次。由于我们每次获取的接口(api)实例都是传入的class对象,而class对象是在进程内单例的,所以获取她的同一个方法Method实例也是单利的,所以这个缓存是有效的。

既然是缓存,逻辑就是如果缓存里面有,则直接从缓存里面拿,如果缓存没有,则new一个ServiceMethod.Builder对象,然后调用它的build()方法来获取一个ServiceMethod,并把它放入serviceMethodCache中,然后返回。

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

Builder构造中,传入了Retrofit 对象和循环出来的方法并赋值。通过这个方法,找到它上面的注解和参数的类型和方法的参数上的注解 比如GitHubService 中的@GET,List,@Path

然后看其build()方法

 public ServiceMethod build() {
      //获取callAdapter
      callAdapter = createCallAdapter();
      //通过callAdapter的responseType方法获取响应体类型
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
       //获取响应转化器
      responseConverter = createResponseConverter();
       //遍历方法的注解
      for (Annotation annotation : methodAnnotations) {
        //解析方法注解
        parseMethodAnnotation(annotation);
      }
       //如果没有HTTP请求的方法,则抛异常
      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }
      //在上面遍历方法注解并解析方法注解的时候,hasBody,isMultipart,isFormEncoded等已经完成赋值
      //如果没有请求体
      if (!hasBody) {
        //如果使用了@Multipart注解,使用了@Multipart 是必须有消息体的
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        //如果使用了 @FormEncoded,使用了@FormEncoded 是必须有消息体的
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }
      //入参的注解,它的长度也就是有多少个入参,遍历每个入参对应的注解
      int parameterCount = parameterAnnotationsArray.length;
      //创建对应的数量的参数处理类数组,这时候开始处理入参对应的注解了
      parameterHandlers = new ParameterHandler<?>[parameterCount];
       //遍历入参的数量
      for (int p = 0; p < parameterCount; p++) {
         //首先获取入参的类型
        Type parameterType = parameterTypes[p];
         //如果是不能处理的类型,则抛异常
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }
         //如果是可以处理的类型获取对应位置入参的注解
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        //如果对应入参的注解为null,则抛异常
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        //如果对应的入参注解不为null,则调用parseParameter方法获取ParameterHandler,
        //cancel在这里方法里面创建ParameterHandler里面的静态内部类
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
       //for循环遍历以后,如果relativeUrl还为null,同时没有使用!@url注解,
       //这样的话我们就无法获取url地址了,所以要抛异常。
      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      //如果没有使用@FormEncoded注解、@Multipart和,同时HTTP请求方式也不需要响应提,但是却使用了@Body 注解,
      //这不是自相矛盾,所以抛异常。
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      //如果使用@FormEncoded注解,却没使用@Field注解,不符合规范,则抛异常
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      //如果使用 @Multipart 注解,却没有使用@Part 注解,抛异常
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }
       //new一个ServiceMethod对象,入参是Builder自己,然后return这个ServiceMethod对象。
      return new ServiceMethod<>(this);
    }

**第一步通过createCallAdapter()方法创建了CallAdapter对象。**Call的转化适配器

  private CallAdapter<T, R> createCallAdapter() {
      //获取方法的返回值类型
      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);
      }
    }

可以看到,首先拿到方法的返回类型,判断这个返回类型合不合法是不是void之后拿到方法的注解参数集合。最后通过retrofit.callAdapter(returnType, annotations);创建并返回。

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

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");
     //获取skipPast的位置,skpiPost跳过去
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      //通过CallAdapter.Factory的get方法来获取对应的CallAdapter
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
       //如果adapter不为null,则返回adapter
      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());
  }

最终调用了nextCallAdapter方法 其内部循环callAdapterFactories拿出CallAdapter.Factory并调用其get方法。
如果我们添加了RxJava2CallAdapterFactory就执行RxJava2CallAdapterFactory的get方法创建自己,如果没有添加,就创建系统默认的DefaultCallAdapterFactory。

第二步通过createResponseConverter()创建Converter

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中的nextResponseBodyConverter方法

  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    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");
    //获取跳过的skipPast对象的位置,然后加1
    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
    //获取对应的 Converter.Factory对象,然后调用requestBodyConverter()方法,
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
       //由于requestBodyConverter()默认是返回null,所以只有重写过才会不为null
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
     // 如果遍历了,还是没有合适的,则抛异常
    StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
        .append(type)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
      }
      builder.append('\n');
    }
    builder.append("  Tried:");
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    throw new IllegalArgumentException(builder.toString());
  }

循环converterFactories拿出我们配置的Converter.Factory,执行其responseBodyConverter方法。我们一开始指定了.addConverterFactory(GsonConverterFactory.create())所以就是GsonConverterFactory的responseBodyConverter方法来获取GsonConverterFactory实例。

第三步循环方法的注解并解析并检查for(Annotation annotation : methodAnnotations) {parseMethodAnnotation(annotation); }

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

获取请求的方法类型,通过parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)给相对地址relativeUrl和相对地址的name,relativeUrlParamNames赋值。

第四步循环解析参数的注解

具体解析方法通过parseParameter来实现

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

        if (annotationAction == null) {
          continue;
        }

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

        result = annotationAction;
      }

      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }

      return result;
    }

可以看到parseParameter方法内部其实也是遍历这个参数的所有注解,然后通过调用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的静态内部类对象。最终保存在ServiceMethod的数组parameterHandlers中。

第五步,判断一些约束之后,开始创建ServiceMethod对象

return new ServiceMethod<>(this);

这就分析完了eagerlyValidateMethods()方法。它主要是通过ServiceMethod的builder来创建ServiceMethod对象并对其内部参数赋值。

下面开始看Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法
可以看到,这里运用了java的动态代理,Proxy.newProxyInstance方法返回的就是我们的接口GitHubService的代理对象。 invoke方法就是接口方法的具体实现,invoke()方法里面的method为具体的方法(在demo就是GitHubService 中的 listRepos方法);args是该方法的参数。
看看InvocationHandler()中
(1)判断是不是Object的方法,如果是直接执行invoke方法
(2)看看是不是平台默认的方法。这个永远返回false不执行
(3)调用loadServiceMethod()方法解析数据,如果缓存中有,直接取出,没有就创建。跟eagerlyValidateMethods()中的是一个方法。loadServiceMethod()方法主要是吧将一个接口的方方法的调用适配成一个HTTP的Call
(4)用serviceMethod和args作为参数,构造一个OkHttpCall对象。OkHttpCall是retrofit2.Call接口的实现类,主要用来执行同步和异步的网络请求。
(5)调用serviceMethod的callAdapter对象的adapt(OkHttpCall)方法获取一个代理实现类的对象并返回。比如上面的例子返回GitHubService对象,如果使用rxjava可能返回Observable对象。

好长啊,创建工作完成,下一篇在看执行工作

总结:
这一篇主要分析了Retrofit的创建和Service的创建。Retrofit的创建主要是初始化一系列的参数,如基url,请求和响应的转换器工厂集合,请求Call的适配器工厂集合,回调执行器,网络请求工厂等。
Service的创建通过Retrofit中的create方法,这是Retrofit的核心方法之一,通过动态代理,把我们定义的service接口,转化成为可执行的OkHttpCall。最后通过serviceMethod的callAdapter对象的adapt(OkHttpCall)方法适配成一个我们想要的代理实现类的对象并返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值