Retrofit 2.0源码解析

简介

刚接触Retrofit的时候,就写了一篇简单的使用介绍:Retrofit 2.0基本使用方法,算是对Retrofit的基础入门。也算是接触Retrofit一段时间了,现在差不多可以对源码层进行解析,最起码,理解原理后可以使得我们使用起来更加得心应手 _

网络请求使用基本方法

参考官网:

Introduction

Retrofit turns your HTTP API into a Java interface.

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

The Retrofit class generates an implementation of the GitHubService interface.

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();
GitHubService service = retrofit.create(GitHubService.class);

Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.

Call<List<Repo>> repos = service.listRepos("octocat");
//synchronous request
repos.execute();
//asynchronous request
repos.enqueue(new Callback<ResponseBody>() {/***/});

Use annotations to describe the HTTP request:

URL parameter replacement and query parameter support
Object conversion to request body (e.g., JSON, protocol buffers)
Multipart request body and file upload

源码解析: retrofit:2.3.0

从上一节的使用Retrofit进行网络请求中,我们可以看到,请求过程主要分为以下几步:

  1. 创建一个接口进行HTTP请求描述;
  2. 使用Retrofit.Builder构建模式构造出一个Retrofit实例;
  3. 调用retrofit.create()方法获取请求接口实例;
  4. 由请求接口实例获取到Call对象;
  5. 进行网络请求(同步/异步)

接下来,我们就按照以上正常的网络请求顺序来对Retrofit源码进行解析。

  • 创建一个接口进行HTTP请求描述
public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

这里主要做的就是采用注解的方式进行HTTP描述,后面在第4步由请求接口实例获取到Call对象时进行反射提取注解内容进行HTTP请求构造(如果开启了预先加载解析(validateEagerly=true),那么在第3步调用retrofit.create()方法获取请求接口实例的时候就会进行注解解析),具体解析方法参考后续分析。

  • 使用Retrofit.Builder构建模式构造出一个Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

那我们就先来看下Retrofit.Builder部分源码:

  /**
     * Build a new {@link Retrofit}.
     * <p>
     * Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
     * are optional.
     */
    public static final class Builder {
        private final Platform platform;
        //callFactory通过newCall(Request request)方法,返回一个okhttp3.Call对象,以便让我们进行实际的HTTP请求
        //也就是说callFactory是我们用来生成一个客户端HTTP请求工厂实例
        private @Nullable okhttp3.Call.Factory callFactory;
        private HttpUrl baseUrl;
        //converterFactories生产Converter<F, T>,用于将HTTP返回结果F类型转换为T类型,或将HTTP请求类型F转换为T。
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        //adapterFactories生产 CallAdapter<R, T>,用于将retrofit2.Call<R>网络请求类型转换为T类型:T adapt(Call<R> var1);
        private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
        private @Nullable
        Executor callbackExecutor;
        private boolean validateEagerly;
        ···
        ···
        ···
}

Retrofit.Builder的注释中,我们可以看到,在调用Retrofit.Builder.build()之前,除了baseUrl()是必须配置的以外,其他的内容都是可选配置。
这里要对两个类型做下讲解,因为笔者在刚分析Retrofit源码时,被这两个类型的概念弄得头晕眼胀,好在一顿分析后,终于有了一点眉目,这两个类型就是:Converter<F, T>CallAdapter<R, T>

  • Converter<F, T>:数据转换器,用来将HTTP请求返回结果由F类型转换为T类型,或者将HTTP请求类型F转换为T
/**
 * Convert objects to and from their representation in HTTP. Instances are created by {@linkplain
 * Factory a factory} which is {@linkplain Retrofit.Builder#addConverterFactory(Factory) installed}
 * into the {@link Retrofit} instance.
 */
public interface Converter<F, T> {
  T convert(F value) throws IOException;
          ···
          ···
          ···
}

举例:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

上面配置了ConverterFactoryGsonConverterFactory,那么当HTTP请求结果返回时,就会由GsonConverterFactory产生的Converter,假设为Converter<ResponseBody, List<Repo>>,该Converter就会将HTTP返回结果ResponseBody转换为 List<Repo>
而若是将对象转换为数据,那么假设类型为:Converter< List<Repo>, RequestBody>,该Converter在构建请求体时,会将List<Repo>转换为RequestBody对象。

  • CallAdapter<R, T>:请求适配器,用于将retrofit2.Call<R>网络请求类型转换为T类型
/**
 * Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
 * created by {@linkplain Factory a factory} which is
 * {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit}
 * instance.
 */
public interface CallAdapter<R, T> {
  /**
   * Returns the value type that this adapter uses when converting the HTTP response body to a Java
   * object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
   * is used to prepare the {@code call} passed to {@code #adapt}.
   * <p>
   * Note: This is typically not the same type as the {@code returnType} provided to this call
   * adapter's factory.
   */
  Type responseType();

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   * <p>
   * For example, given an instance for a hypothetical utility, {@code Async}, this instance would
   * return a new {@code Async<R>} which invoked {@code call} when run.
   * <pre><code>
   * @Override
   * public <R> Async<R> adapt(final Call<R> call) {
   *   return Async.create(new Callable<Response<R>>() {
   *     @Override
   *     public Response<R> call() throws Exception {
   *       return call.execute();
   *     }
   *   });
   * }
   * </code></pre>
   */
  T adapt(Call<R> call);
  /**
   * Creates {@link CallAdapter} instances based on the return type of {@linkplain
   * Retrofit#create(Class) the service interface} methods.
   */
              ···
              ···
              ···
}

举例:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")      
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

上面配置了CallAdapterFactoryRxJava2CallAdapterFactory,这里的作用就是将Retrofit2.Call<T>对象转换为Observable<T>类型,所以如果配置了RxJava2CallAdapterFactory,那么接口方法声明应该改为如下形式:

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

其实这个addCallAdapterFactory实现原理是挺简单的,因为Retrofit里面维护了CallAdapter.Factory一个数组,在使用Builder配置的时候,所有配置的CallAdapter.Factory最后都会保存到Retrofit那个数组中,后面在进行转换是,Retrofit会根据接口方法返回结果类型(此处为:Observable<List<Repo>>),遍历CallAdapter.Factory数组,找到一个能处理该返回类型的CallAdapter后,就不再遍历。更多具体的解析方法请参考后续整体流程的介绍。

上面讲了那么多的东西,可是还是没有讲到Retrofit实例的创建,别着急,在查看Retrofit.Builder.build()方法前,我们还要看下Builder的构造函数:

        Builder(Platform platform) {
            this.platform = platform;
            // Add the built-in converter factory first. This prevents overriding its behavior but also
            // ensures correct behavior when using converters that consume all types.
            converterFactories.add(new BuiltInConverters());
        }

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

当我们调用:

new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .build();

就会走入:Builder()--> Builder(Platform platform)
然后我们看到,在Builder(Platform platform)构造函数里面,会往converterFactories里面添加进一个BuiltInConverters对象,所以默认的ConverterFactory就是BuiltInConverters。前面说过ConverterFactory主要是用来将HTTP返回结果进行类型转换或者将HTTP请求体进行类型转换,然后我们看下BuiltInConverters是怎样的转换方式:

final class BuiltInConverters extends Converter.Factory {
  //返回结果转换
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      //如果annotations是Streaming类型
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

  //请求转换
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }

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

    @Override public Void convert(ResponseBody value) throws IOException {
      value.close();
      return null;
    }
  }

  static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

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

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

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

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

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
        // Buffer the entire body to avoid future I/O.
        return Utils.buffer(value);
      } finally {
        value.close();
      }
    }
  }

  static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }
}

返回结果转换的时候,有3种情况:

  • 如果返回类型是ResponseBody类型,那么可能返回的是:StreamingResponseBodyConverter.INSTANCE或者BufferingResponseBodyConverter.INSTANCE,再跟踪进去这两个类里面的convert函数:
 @Override public ResponseBody convert(ResponseBody value){···}

发现传入的是ResponseBody,返回的也是ResponseBodyBufferingResponseBodyConverter里面有进行特殊处理,主要是为了去除future I/O),所以我们可以认为BuiltInConverters对HTTP返回结果没有进行转换处理。

  • 如果返回类型是Void类型,那么最终就将ResponseBody资源关闭后,直接返回null
  • 如果返回类型不是ResponseBodyVoid类型,直接返回null

同理,我们来看下请求体转换:

//请求转换
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

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

可以看到,如果是RequestBody类型,那就不转换,如果不是RequestBody类型,直接返回null

综上所述:BuiltInConverters只能响应ResponseBodyRequestBody,但是并不进行任何转换.对于其他类型,统统返回null。

到这里,终于可以走进Retrofit.Builder.build()函数,一窥究竟:

 /**
         * Create the {@link Retrofit} instance using the configured values.
         * <p>
         * Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
         * OkHttpClient} will be created and used.
         */
        public Retrofit build() {
            if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }

            okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                //callFactory默认为OkHttpClient
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                //默认的callbackExecutor为Platform.Android.MainThreadExecutor
                //MainThreadExecutor继承Executor,并复写execute(Runnable r),
                // execute内部直接通过主线程Handler.post(r),即r.run发生在主线程
                callbackExecutor = platform.defaultCallbackExecutor();
            }

            // Make a defensive copy of the adapters and add the default Call adapter.
            List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
            //defaultCallAdapterFactory是ExecutorCallAdapterFactory
            adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

            // Make a defensive copy of the converters.
            //BuiltInConverters在Retrofit.Builder(Platform)构造时,已被传入
            List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

build函数一进去,就看到:

if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }

这说明baseUrl是一定要进行配置的,否则程序就会抛出异常,这跟我们上面讲到的一致。
接着往下看:

     okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                //callFactory默认为OkHttpClient
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                //默认的callbackExecutor为Platform.Android.MainThreadExecutor
                //MainThreadExecutor继承Executor,并复写execute(Runnable r),
                // execute内部直接通过主线程Handler.post(r),即r.run发生在主线程
                callbackExecutor = platform.defaultCallbackExecutor();
            }

这里可以看到,如果没有配置okhttp3.Call.Factory,那么就会使用默认的HTTP工厂类:OkHttpClient,用于客户端程序创建okhttp3.Call对象,以进行实际的HTTP网络请求。
如果没有线程调度器callbackExecutor,那么就会使用默认的线程调度器:Platform.Android.MainThreadExecutor

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

从源码可以看出,默认的线程调度器是主线程调度器。
接下来再看:

 // Make a defensive copy of the adapters and add the default Call adapter.
            List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
            //defaultCallAdapterFactory是ExecutorCallAdapterFactory
            adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

可以看到,这里为adapterFactories增加了一个CallAdapterFactory:

//Platform.java
 CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        if (callbackExecutor != null) {
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }
        return DefaultCallAdapterFactory.INSTANCE;
    }
//ExecutorCallAdapterFactory.java
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
    final Executor callbackExecutor;

    ExecutorCallAdapterFactory(Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
    }

    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
            return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Object, Call<?>>() {
            @Override
            public Type responseType() {
                return responseType;
            }

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

    static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
        final Executor callbackExecutor;
        //HTTP请求委托类
        final retrofit2.Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }
        //异步请求
        @Override
        public void enqueue(final Callback<T> callback) {
            checkNotNull(callback, "callback == null");

            delegate.enqueue(new Callback<T>() {
                @Override
                public void onResponse(Call<T> call, final Response<T> response) {
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            if (delegate.isCanceled()) {
                                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                            } else {
                                callback.onResponse(ExecutorCallbackCall.this, response);
                            }
                        }
                    });
                }

                @Override
                public void onFailure(Call<T> call, final Throwable t) {
                    callbackExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            callback.onFailure(ExecutorCallbackCall.this, t);
                        }
                    });
                }
            });
        }
        //同步请求
        @Override
        public Response<T> execute() throws IOException {
            return delegate.execute();
        }
       ···
      ···
      ···
}

在Android平台上,callbackExecutor默认不为null,所以defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory。从ExecutorCallAdapterFactoryget函数,可以看到,ExecutorCallAdapterFactory只会响应返回类型为Call的函数声明(所以,如果我们没有配置addCallAdapterFactory(),那么我们接口函数声明的返回类型必须为Call<?>),响应处理的最终结果就是返回一个CallAdapter,这个CallAdapteradapt()函数会传入一个HTTP请求委托类,然后返回一个HTTP请求代理类:ExecutorCallbackCall<T> implements retrofit2.Call<T>,这个代理类代理了委托类的异步HTTP网络请求,并将返回结果通过线程调度器将回调监听函数分发到具体线程上执行(默认线程调度器是主线程调度)。

讲到这里,Retrofit实例的配置创建就算是完成了。下面这个图展示了Retrofit.Builder提供的配置选项:

Builder

  • 调用retrofit.create()方法获取请求接口实例
GitHubService service = retrofit.create(GitHubService.class);

那我们接下来就看一下create()的源码:

 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
    public <T> T create(final Class<T> service) {
        //1.是否是接口
        //2.不能继承其他接口
        Utils.validateServiceInterface(service);
        //预先加载解析注解:loadServiceMethod
        //默认false,即调用接口方法后,才进行解析
        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);
                        }
                        //java8平台使用
                        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);
                    }
                });
    }

这里我们可以看到,create方法返回的是一个 (T) Proxy.newProxyInstance()方法产生的一个动态代理对象(如果不清楚动态代理,可以看下我之前写的文章:Java代理模式,里面对java的动态代理有详细讲解)。使用该动态代理对象进行方法调用后,会自动被InvocationHandler拦截,最终进入InvocationHandlerinvoke函数里面。

  • 由请求接口实例获取到Call对象
Call<List<Repo>> repos = service.listRepos("octocat")

从上面create的分析中,我们知道,此处的service是一个动态代理类对象,所以,在调用方法时,会被InvocationHandlerinvoke方法拦截,所以调用:service.listRepos("octocat")就会进入InvocationHandler.invoke()中,查看下invoke函数,最主要的操作就是如下3句话:

 ServiceMethod<Object, Object> serviceMethod =
                                (ServiceMethod<Object, Object>) loadServiceMethod(method);
                        OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                        return serviceMethod.callAdapter.adapt(okHttpCall);

ServiceMethodRetrofit中是一个很重要的类,主要做的就是对接口方法注解进行解析,最终生成一个Request

那我们先来看下loadServiceMethod()源码:

ServiceMethod<?, ?> loadServiceMethod(Method method) {
        ServiceMethod<?, ?> result = serviceMethodCache.get(method);
        if (result != null) return result;

        synchronized (serviceMethodCache) {
            result = serviceMethodCache.get(method);
            if (result == null) {
                result = new ServiceMethod.Builder<>(this, method).build();
                serviceMethodCache.put(method, result);
            }
        }
        return result;
    }

serviceMethodCache是一个缓存容器,是对接口方法的解析缓存。

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

loadServiceMethod()中可以看到,ServiceMethod的实例也是通过builder模式进行构建的,构建过程需传入Retrofit对象和Method对象。

Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //取得接口方法的注解
      this.methodAnnotations = method.getAnnotations();
      //返回接口方法参数类型
      this.parameterTypes = method.getGenericParameterTypes();
      //返回接口方法各个参数注解
      //按参数声明顺序排列,每个参数可能有多个注解,故二维数组
      //parameterAnnotationsArray[0][i]:第一个参数第i个注解
      //parameterAnnotationsArray[1][j]:第二个参数第j个注解
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

public ServiceMethod build() {
      //CallAdapter<T, R> callAdapter;适配Call的响应类型,将默认响应类型R转换为类型T
      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<ResponseBody, T> responseConverter;HTTP交互中,转换对象为数据 或 从数据转换为对象
      responseConverter = createResponseConverter();

      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.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      ···
      ···
      return new ServiceMethod<>(this);
    }

ServiceMethod.Builder.build()源码中可以看到:

callAdapter = createCallAdapter();

首先创建一个callAdapter,具体创建过程如下:

private CallAdapter<T, R> createCallAdapter() {
      //接口方法return类型
      Type returnType = method.getGenericReturnType();
     ···
      ···
      Annotation[] annotations = method.getAnnotations();
        //noinspection unchecked
      ···
      ···
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
    }

可以看到,其最终调用到的是retrofit.callAdapter()

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

/**
     * Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
     * #callAdapterFactories() factories} except {@code skipPast}.
     *
     * @throws IllegalArgumentException if no call adapter available for {@code type}.
     */
    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                             Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");

        // final List<CallAdapter.Factory> adapterFactories;
        int start = adapterFactories.indexOf(skipPast) + 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;
            }
        }

        //throw exception
       ···
        ···
    }

可以看到,createCallAdapter()就是从RetrofitList<CallAdapter.Factory> adapterFactories数组中,遍历找到一个可以处理该接口方法返回类型和注解的CallAdapter<?, ?>。那根据我们之前的分析,如果我们没有进行CallAdapter的配置,那么默认的CallAdapter就是ExecutorCallAdapterFactory.get(Call.class,xxx,retrofit);

public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if(getRawType(returnType) != Call.class) {
            return null;
        } else {
            final Type responseType = Utils.getCallResponseType(returnType);
            return new CallAdapter<Object, Call<?>>() {
                public Type responseType() {
                    return responseType;
                }

                public Call<Object> adapt(Call<Object> call) {
                    return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
                }
            };
        }
    }

可以看到,默认的CallAdapter.Factory只会响应接口方法返回类型为Call,所以遍历adapterFactories的时候,如果接口方法返回类型不是Call,那么ExecutorCallAdapterFactory.get()自然返回的就是null,然后就会继续找下一个CallAdapterFactory,继续尝试,直到找到能处理该接口方法返回类型的CallAdapterFactory,由其返回一个CallAdapter

上面的流程可以这样想(较为生动):
createCallAdapter说:retrofit,给我一个能处理我这个接口方法返回类型(假设为Observable<T>)的CallAdapter
retrofit接收到请求后,就会从自己的adapterFactories仓库中一个一个的进行询问:
首先找到默认的CallAdapter.Factory:ExecutorCallAdapterFactory,然后说:ExecutorCallAdapterFactory啊,你能处理Observable<T>这个返回类型吗?
ExecutorCallAdapterFactory一看,说:retrofit啊,你给我的返回类型不是Call类型,我没办法处理,你找下一位CallAdapter.Factory仁兄吧。
既然默认的ExecutorCallAdapterFactory没办法处理这个接口方法返回类型,那retrofit就只能继续问下一位CallAdapter.Factory啦,假设下一位是RxJava2CallAdapterFactory,然后,retrofit开始发问,说:RxJava2CallAdapterFactory仁兄呀,你能处理Observable<T>这个返回类型吗?
RxJava2CallAdapterFactory一看,说:retrofit兄啊,你这个Observable<T>我拿手呀,随随便便进行处理,处理的结果拿到了这个CallAdapter,你赶紧拿着给createCallAdapter交差吧。
retrofit一听,太高兴了,说到:RxJava2CallAdapterFactory兄啊,您真牛逼,谢谢您了,好的好的,我赶紧拿着您给的CallAdaptercreateCallAdapter交差,那边催的紧呢。
于是,retrofit高高兴兴地就往createCallAdapter那边赶了,adapterFactories后面还没问到的兄弟就不管了,没办法,哥(retrofit)时间紧,没有那么多时间去一 一问候兄弟们,望兄弟们见谅 _

我们接着看ServiceMethod.Builder.build()方法,可以看到,createCallAdapter后,又createResponseConverter了:

 //Converter<ResponseBody, T> responseConverter;HTTP交互中,转换对象为数据 或 从数据转换为对象
      responseConverter = createResponseConverter();

responseConverterConverter<ResponseBody, T>类型,其实我们一看到这个,就应该大概知道是怎么做了,肯定又是跟retrofit请求,retrofit又从仓库中进行查找,只是这回是从List<Converter.Factory> converterFactories中查找,直到找到一个能处理这种responseTypeConverter.Factory,由其返回一个Converter。让我们看下源码是不是这样的:

//ServiceMethod.java
    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.java
 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, annotations);
    }
   /**
     * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
     * {@linkplain #converterFactories() factories} except {@code skipPast}.
     *
     * @throws IllegalArgumentException if no converter available for {@code type}.
     */
    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
            @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");

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

可以看到,跟我们上面所说的过程是一样的。
还记得吗,有一个默认的retrofit2.Converter.Factory是:BuiltInConverters。那从BuiltInConverters得到的Converter<ResponseBody, T>是什么呢,根据我们之前的分析:

  • 如果responseTypeResponseBody类型,那么返回的还是ResponseBodyBufferingResponseBodyConverter有经过一些处理);
  • 如果responseTypeVoid类型,那么释放ResponseBody资源,然后返回null;
  • 其他responseType类型,直接返回null

所以,如果我们没有配置addConverterFactory,那么接口返回类型应该声明为Call<ResponseBody>或者Call<Void>这类型的,这样,默认的retrofit2.Converter.Factory才能进行处理

接着看Retrofit.Builder.build()方法,可以看到:

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

可以看到里面对很多方法都进行了解析,这里,我们就只拿GET方法解析源码来分析下解析流程,其余方法解析都是类似的:

parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);

  private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
     ···
      ···
      ···
      this.relativeUrl = value;
      this.relativeUrlParamNames = parsePathParameters(value);
    }

按照官网那个例子,那么:this.relativeUrl = value = "users/{user}/repos",在parseHttpMethodAndPath最后,调用了 parsePathParameters(value)

/**
   * Gets the set of unique path parameters used in the given URI. If a parameter is used twice
   * in the URI, it will only show up once in the set.
   */
  static Set<String> parsePathParameters(String path) {
    Matcher m = PARAM_URL_REGEX.matcher(path);
    Set<String> patterns = new LinkedHashSet<>();
    while (m.find()) {
      patterns.add(m.group(1));
    }
    return patterns;
  }

这里采用正则表达式取出形如"{*}"这种结构的内容,保留在全局Set<String> relativeUrlParamNames集合里面。
像官网这个例子,当程序来到parsePathParameters("users/{user}/repos")的时候,正则表达式就获得了user这个字符串,并存储到全局relativeUrlParamNames里面。这样,接口方法的可变字符串就被记录了起来,后续只要获取到参数注解内容的名字是一样的(eg:@Path("user") String user,参数注解内容是"user“),将参数转换(Converter,默认为StringConverter,转换就是直接调用参数对象的toString()方法转成字符串)放入方法路径可成为一个真正的relativeUrl
以上就是方法注解的解析过程。

但是接口方法参数的注解还没进行解析,那我们就继续往下看ServiceMethod.Builder.build()方法,可以看到:

 //有多少个参数带注解
      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.");
        }
        //根据参数类型和对应注解集合进行解析,封装到parameterHandlers中
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

参数注解解析过程的最后调用了:parseParameter,这个方法会根据传入的参数类型和对应注解集合进行解析,封装成为ParameterHandler,将每个参数的注解解析最后都存入到parameterHandlers数组中,所以parameterHandlers[0]就是第一个带注解的参数的解析内容,parameterHandlers[1]就是第二个带注解的参数的解析内容····:

 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,这个方法内部代码特别长,因为有很多种注解需要分析,在这里,我们就只抽取出@Path的注解解析部分内容:

 //参数注解解析
    private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
        ····
        ····
        ····
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();
        /**
         * 有效性检验:
         * 1.命名规范:必须符合正则:[a-zA-Z][a-zA-Z0-9_-]*
         * 2.注解value必须存在relativeUrlParamNames方法变量,对应起来
         */
        validatePathName(p, name);

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

这里对@Path的解析最主要的就是获取一个Converter<?, String>,获取是通过retrofit.stringConverter()

 /**
     * Returns a {@link Converter} for {@code type} to {@link String} from the available
     * {@linkplain #converterFactories() factories}.
     */
    public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");

        for (int i = 0, count = converterFactories.size(); i < count; i++) {
            Converter<?, String> converter =
                    converterFactories.get(i).stringConverter(type, annotations, this);
            if (converter != null) {
                //noinspection unchecked
                return (Converter<T, String>) converter;
            }
        }

        // Nothing matched. Resort to default converter which just calls toString().
        //noinspection unchecked
        return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
    }

同样,这里是通过遍历converterFactories,找到一个能处理这种类型typeConverter.Factory,返回一个 Converter<?, String>,如果找不到,就使用BuiltInConverters.ToStringConverter.INSTANCE。查看下BuiltInConverters.ToStringConverter.INSTANCE源码:

//BuiltInConverters.java
static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }

可以看到,默认的StringConverter就是通过调用paramter对象的toString方法,直接将结果类型转成String类型。
到这里,我们就明白了:

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

接口方法参数user的类型其实可以不用是String类型,就算是其他类型也可以,但是默认的StringConverter调用该类型对象的toString方法返回的结果要符合你自己需求。
比如,我们现在自定义一个java bean:

public class StringWrapper {
    private String content;
    public StringWrapper(String content)
    {
        this.content = content;
    }

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

这样也是可以的,因为StringWrapper.toString跟我们上面直接定义成的String最终结果是一样的。
回到正题,parseParameterAnnotation中对@Path的解析最终会返回一个ParameterHandler.Path对象:

static final class Path<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;

    Path(String name, Converter<T, String> valueConverter, boolean encoded) {
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }

    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) {
        throw new IllegalArgumentException(
            "Path parameter \"" + name + "\" value must not be null.");
      }
      builder.addPathParam(name, valueConverter.convert(value), encoded);
    }
  }

最后,参数解析所有的信息都放入到了全局数据parameterHandlers中,没个parameterHandlers[i]都包含了各个参数的所有注解解析信息。

ParameterHandler<T>

到这里,ServiceMethod.Builder.build()方法也算是解析完毕了。
总结一下:ServiceMethod的创建过程主要做了几件事:

  1. 根据接口方法返回类型,通过遍历retrofitadapterFactories列表,找到适合的CallAdapter<T, R> callAdapter
  2. 根据HTTP返回结果类型,通过遍历retrofitconverterFactories列表,找到适合的Converter<ResponseBody, T> responseConverter
  3. 对接口方法注解进行解析:parseMethodAnnotation(Annotation annotation)
  4. 对接口方法参数注解进行解析:parseParameter
  5. 完成以上工作后,创建ServiceMethod对象。

最后,用一张图来表达下ServiceMethod的创建过程:

ServiceMethod.Builder.build

现在继续分析Retrofit.createInvocationHandler的invoke剩余部分源码:

 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

这里创建了一个okHttpCall

final class OkHttpCall<T> implements retrofit2.Call<T> {
        ···
        ···
 @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall;
        ···
}
OkHttpCall<T>

这里可以看到OkHttpCall内部持有一个okhttp3.Call,所以其实OkHttpCall所进行的HTTP请求实际上都是交由okhttp3.Call进行的。

InvocationHandlerinvoke最后返回了:

return serviceMethod.callAdapter.adapt(okHttpCall);

经过前面的分析,假设我们对Retrofit没有经过特殊配置,即Retrofit采用默认配置,那么:serviceMethod.callAdapter返回的就是默认的ExecutorCallAdapterFactory.get(Call.class,annotations,retrofit)

//ExecutorCallAdapterFactory.java
@Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

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

serviceMethod.callAdapter.adapt(okHttpCall)返回的就是一个new ExecutorCallbackCall<>(callbackExecutor, okHttpCall)的对象。

static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
        final Executor callbackExecutor;
        //HTTP请求委托类
        final retrofit2.Call<T> delegate;

        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
            this.callbackExecutor = callbackExecutor;
            this.delegate = delegate;
        }

这里可以看到,ExecutorCallbackCall就是okHttpCall的代理类,而okHttpCall又持有okhttp3.Call实例。因此,进行HTTP请求的过程就明晰了:
ExecutorCallbackCall.enqueue-->okHttpCall.enqueue-->okhttp3.Call.enqueue
ExecutorCallbackCall持有的Executor callbackExecutor默认是主线程调度器,会将ExecutorCallbackCall发送HTTP请求的返回结果回调到主线程上执行。

那我们最后就来看一下发送网络请求的具体过程。

  • 进行网络请求(同步/异步)

网络请求是通过我们得到的ExecutorCallbackCall<>(callbackExecutor, okHttpCall)对象进行请求,这里就只看下异步请求过程:

repos.enqueue(new Callback<ResponseBody>() {/***/});

上面分析知道,ExecutorCallbackCall内部封装了网络请求和线程调度作用,而实际起网络请求作用的是OkHttpCall
那我们就来看下OkHttpCall的异步网络请求enqueue源码:

@Override 
 public void enqueue(final Callback<T> callback) {
        ···
        ···
        okhttp3.Call call;
        ···
        ···

        call = rawCall = createRawCall();
        ···
        ···

        call.enqueue(new okhttp3.Callback() {
                @Override
                public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
                throws IOException {
                        Response<T> response;
                        ···
                        ···
                        callSuccess(response);
                }

                @Override
                public void onFailure(okhttp3.Call call, IOException e) {
                        ···
                        callback.onFailure(OkHttpCall.this, e);
                        ···
                }
                        ···
                        ···
        }
}

可以看到,OkHttpCall里面是通过函数createRawCall获得一个真正的能用于HTTP网络请求的okhttp3.Call对象,那么我们就来看下createRawCall()源码是怎样构建出一个okhttp3.Call对象:

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

这里,我们先来看下:

okhttp3.Call call = serviceMethod.callFactory.newCall(request);

serviceMethod.callFactory默认就是retrofitcallFactory,也就是OkHttpClient,所以这里就是由OkHttpClient创建出一个真正用于进行HTTP网络请求的okhttp3.Call对象。

接下来我们回顾上一行代码,可以看到是通过serviceMethod.toRequest(args)构建出一个Request,此处的args就是我们接口方法的参数,那么我们就先来看下serviceMethod.toRequest源码是怎样构建一个Request的:

 /** Builds an HTTP request from method arguments. */
  Request toRequest(@Nullable Object... args) throws IOException {
//从接口方法注解解析信息
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
//接口方法参数注解解析信息
    ParameterHandler<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();
  }

所以我们前面为什么说ServiceMethodRetrofit里面是很重要的,在这里也可以知道,ServiceMethod既负责解析接口方法,接口参数,又负责从retrofit那边获取合适的CallAdapter和Converter,又要负责将接口解析出来的内容组装成一个HTTP Request···可以说,ServiceMethod就是Retrofit的核心引擎。
回到toRequest函数,从上面的源码中可以看到,首先是根据接口方法解析的信息组装成了一个RequestBuilder,然后再根据方法参数信息(Object... args),经由之前解析的参数注解信息可以得到一个最终的RequestBuilder,由这些信息就可以build出一个Request
toRequest里面有句代码是:

handlers[p].apply(requestBuilder, args[p]);

这里其实获取得到的就是接口方法第p个参数解析出来的效果,举个例子来说,比如,我们之前handlers[p]解析出来的是@Path的信息,那么handlers[p]就是一个ParameterHandler.Path类型的对象,而ParameterHandler.PathParameterHandler静态内部类,同时也是一个ParameterHandler子类:

 static final class Path<T> extends ParameterHandler<T> {
    private final String name;
    private final Converter<T, String> valueConverter;
    private final boolean encoded;

    Path(String name, Converter<T, String> valueConverter, boolean encoded) {
      this.name = checkNotNull(name, "name == null");
      this.valueConverter = valueConverter;
      this.encoded = encoded;
    }

    @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
      if (value == null) {
        throw new IllegalArgumentException(
            "Path parameter \"" + name + "\" value must not be null.");
      }
      builder.addPathParam(name, valueConverter.convert(value), encoded);
    }
  }

所以,handlers[p].apply(requestBuilder, args[p])按官网的例子就变成了:
Path.apply(requestBuilder,String user)-->builder.addPathParam(”user", valueConverter.convert("user"), encoded);
而由我们前面的分析,此处的valueConverter默认是ToStringConverter

 static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }

所以valueConverter.convert("user")-->"user".toString()=="user",所以最终返回的就是字符串"user",所以:
builder.addPathParam(”user", valueConverter.convert("user"), encoded)-->builder.addPathParam(”user", "user", encoded)。
对于@Path来说,肯定是将参数信息替换掉接口方法注解内容相对路径的{*}内容,所以,builder.addPathParam就是实现这个功能的:

void addPathParam(String name, String value, boolean encoded) {
    if (relativeUrl == null) {
      // The relative URL is cleared when the first query parameter is set.
      throw new AssertionError();
    }
    relativeUrl = relativeUrl.replace("{" + name + "}", canonicalizeForPath(value, encoded));
  }

经过以上步骤,就构建出了一个HTTP请求。
最后,我们就可以用这个请求进行真正的网络发送call.enqueue,回顾上面OkHttpCall.enqueue方法,可以看到请求返回结果解析是在:

//OkHttpCall.enqueue片段代码
  call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

可以看到,请求成功的时候,会调用parseResponse得到一个我们需要的Response<T>类型对象,具体解析方法如下:

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    ···
    ···
    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    ···
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    ···
  }

parseResponse就是对得到的rawResponse进行处理判断,最后交由到serviceMethod.toResponse做出最终的转换。

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

可以看到这里就是用到了数据转换器Converter<ResponseBody, R>将HTTP返回结果ResponseBody转换成我们自己定义的类型R(默认的Converter.FactoryBuiltInConverters,它所生产的Convert默认不对ResponseBody进行转换)。

所以分析到了这里,Retrofit整体的流程我们也差不多整理完毕了。

最后进行总结一下:

  • 我们要是用Retrofit进行HTTP网络请求的时候,首先要创建一个接口进行HTTP动作描述,之所以用接口是为了后面动态创建一个对应的接口代理类(java的动态代理只能支持接口);
  • 接口描述创建完成后,通过建造者模式可以配置出一个retrofit实例
  • retrofit的`create函数就可以创建出一个接口的动态代理类
  • 调用动态代理类的接口方法时,就会被动态代理类拦截,拦截的主要原因就是为了隐式的创建出一个用于HTTP网络请求的Call对象,具体做了3件事:
     1. 解析接口注解内容并保存,功能类为ServiceMethod
     2. 创建一个OkHttpCall对象,OkHttpCall内部持有okhttp3.Call实例。OkHttpCall的作用就是从ServiceMethod和当前参数获取得到一个Request,并通过OkHttpClient根据这个Request创建出一个okhttp3.Call对象。
     3. 最后从ServiceMethod中拿到一个可以处理接口方法返回类型的CallAdapter,由其adapt返回得到一个可以对HTTP请求结果进行线程调度的retrofit2.Call对象(该Call对象是OkHttpCall的代理类)。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容