retrofit源码解析

Retrofit 是当下android开发最流行的网络请求框架。用了Retrofit体会到了它的强大之处一直对它的内部实现很感兴趣,花了两天的时间研究了一下它的源码,虽然对里面的设计模式,和为什么要这么做说不出个所以然来,但还是把Retrofit的整个流程搞清楚了。接下来就是记录了一下解析的过程。尽量的写详细点.........

一、retrofit的创建源码解析

众所周知retrofit的创建是用builder模式创建的,最后就是初始化Retrofit里面所需要的成员对象:一个callFactory其实就是OkHttpClient;还有两个factory容器,这里就是工厂模式,分别用来生产解析请求结果(Json数据),和适配网络求情的CallAdapter.

 Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories;
    this.adapterFactories = adapterFactories;
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

按照源码注释来使用Retrofit就是:

For example,
<pre>{@code
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://api.example.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();
MyApi api = retrofit.create(MyApi.class);
Response<User> user = api.getUser().execute();
}</pre>

可以看到创建一个retrofit一般只需要在builder里传入baseUrl和一个GsonConverterFactory因为其他的参数都有默认值,如果不修改就采用默认值了。而且默认值都是在在Builder build()方法里进行初始化:

 public Retrofit build() {
 
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.默认的含有CallAdapter。Factory的容器
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

看,除了一个baseUrl必传入之外,其它的参数要么有默认的初始化要么可以不用传值:

  • okhttp3.Call.Factory callFactory 可以猜到这个是用来进行网络请求的,如果不传入的话,默认的也是用 new OkHttpClient() 来进行初始化;
  • List<CallAdapter.Factory> adapterFactories在Build里申明的时候就已经初始化为一个ArrayList,Bulid在设置CallAdapter的时候只是向里面添加CallAdapter,并且里面一开始就添加了默认的CallAdapterFactory:一个DefaultCallAdapterFactory的对象
/**
     * Add a call adapter factory for supporting service method return types other than {@link
     * Call}.
     */
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

所以Retrofit应该可以支持多个CallAdapter,这个在后面解析过程中再看是用来做什么的吧!

  • 最后是List<Converter.Factory> converterFactories 其实也和List<CallAdapter.Factory> adapterFactories 一样,不过没有往里面加入默认值(猜一下它的作用:它是用来解析Json用的吧)。所以创建一个Retrofit至少就要用:
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://api.example.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();
  • 最后的是一个boolean 值:validateEagerly(java中boolean的值都是false,当然也可以不用我们去初始化), 看一下代买的英文注释:
/**
     * When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
     * the configuration of all methods in the supplied interface.
     */

翻译过来就是 :创建完Retrofit的实例后,当去调用它的create方法时,一开始就(急切的)让这个接口(最后的Service)的方法变得合法化(不管你后面的代理对象能不能创建成功)。(个人理解)还是不懂请看下文

二、Retrofit的使用源码解析

创建好了Retrofit,那我们当然是要调用它的Api了,其实它的Api也就一个:<T> T create(final Class<T> service),就是这个方法。它的作用就是用动态代理模式,产生一个代理对象,可以用这个代理对象替我们完成网络请求,并返回结果。看看代码是怎么写的吧:

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, 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);
            }
            return loadMethodHandler(method).invoke(args);
          }
        });
  }
  
1、判断service类型

一进入这个方法里首先会对service的类型做判断: Utils.validateServiceInterface(service);

static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }

如果service不是接口类型或者service实现了某个接口都会在编译时报错!

2、是否需要提前使方法合理化
if (validateEagerly) {
      eagerlyValidateMethods(service);
    }

这个是上面解析创建时validateEagerly参数初始化的遗留问题,它的作用也就在这一行代码里(决定是否需要提前使方法合理化,具体为什么要这样设计,我也不太清楚),这个eagerlyValidateMethods()方法里面最后调用了loadMethodHandler(method),因为动态代理的时候也会调用,所以这个合理化接口的方法的作用留到后面解释。

3、生成动态代理对象

动态代理这个就不说了吧,如果不了解就可以google或百度一下,return就是一个动态代理对象。动态代理对象调用它的方法返回的是return method.invoke(this, args);当然里面做了判断:

 if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

如果传入的final Class<T> service 是一个Object.class 的话才按照正常的返回,这个呢对动态代理有过了解的应该可能会知道,正常返回意味着什么了(这个返回就是调用代理对象的方法的返回,可以是null但是一定会执行方法)。

这里只对不正常返回做解释了。因为create方法一开始就指定service必须是interface:

MyApi api = retrofit.create(MyApi.class);
Response<User> user = api.getUser().execute();

这里的MyApi是一个接口interface类型的(这里就不是Object了)所以method.getDeclaringClass() == Object.class 会返回false。再往下走:

 if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }

这个platform.isDefaultMethod(method)方法(和java8.0有关吧),不过源码写死的返回false:

  boolean isDefaultMethod(Method method) {
    return false;
  }

那就不管了再往下走,就是关键代码返回了:

 return loadMethodHandler(method).invoke(args);
  1. loadMethodHandler(method)使方法合理化(传入的是一个interface的class对象,interface的方法都没有被实现,当然“不合法”):确定代理对象里包含的的方法名称(当然和接口的方法名称是一样的)+通过解析注释来确定代理对象的这个方法具体要做些什么(当然是网络请求返回结果)。
  2. invoke(args):传入代理对象调用代理对象的方法时需要的参数(进行网络请求的参数)如果代理对象调用了它的方法(进行网络请求),就会返回一个OkHttpCall<>对象(用来进行网络请求:execute());

到这里,这个代理对象的创建也完成了,接下来就是调用的对象的方法,完成网络的请求任务并返回结果了,就像下面使用的代码那样:

MyApi api = retrofit.create(MyApi.class);
Response<User> user = api.getUser().execute();

三、动态代理对象方法调用的原理解析

动态代理对象创建完成时,就可以直接调用它的方法完成相应的任务,那么Retrofit的内部是怎么实现让这个代理对象具备这样的能力的呢?

接到Retrofit的create方法里的最后一行代码看:

return loadMethodHandler(method).invoke(args);

首先我们看一下loadMethodHandler(method)做了什么事情:

 MethodHandler loadMethodHandler(Method method) {
    MethodHandler handler;
    synchronized (methodHandlerCache) {
     ...
      if (handler == null) {
        handler = MethodHandler.create(this, method);
       ...
      }
    }
    return handler;
  }

它就是创建并返回了一个MethodHandler 对象,先看一看MethodHandler 对我们传入的方法做了些什么,才使得传入的方法“合法化”了呢。

首先创建MethodHandler的代码(调用MethodHandler的静态方法create):

 handler = MethodHandler.create(this, method);

这里传入了retrofit本身的实例化对象,和service的方法method对象;下面是create方法的具体内容:

 static MethodHandler create(Retrofit retrofit, Method method) {
    CallAdapter<?> callAdapter = createCallAdapter(method, retrofit);
    Type responseType = callAdapter.responseType();
    if (responseType == Response.class || responseType == okhttp3.Response.class) {
      throw Utils.methodError(method, "'"
          + Types.getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    Converter<ResponseBody, ?> responseConverter =
        createResponseConverter(method, retrofit, responseType);
    RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
    return new MethodHandler(retrofit.callFactory(), requestFactory, callAdapter,
        responseConverter);
  }

先看看new MethodHandler()里需要4个参数:

 MethodHandler(okhttp3.Call.Factory callFactory, 
                    RequestFactory requestFactory,
                    CallAdapter<?> callAdapter, 
                    Converter<ResponseBody, ?> responseConverter)

这4个参数基本上是在MethodHandler 的静态方法里creat()进行初始化的,先看看 CallAdapter<?>初始化吧!

1、用Retrofit的最后一个CallAdapterFactory创建CallAdapter

从这里开始呢,方法“合法化”的操作就会正式开始了,首先创建callAdapter ,先别管他是用来干嘛的,先看看具体实现。通过createCallAdapter(method, retrofit)来创建具体实现是:

 private static CallAdapter<?> createCallAdapter(Method method, Retrofit retrofit) {
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw Utils.methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw Utils.methodError(method, "Service methods cannot return void.");
    }
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw Utils.methodError(e, method, "Unable to create call adapter for %s", returnType);
    }
  }
  1. 检查method的返回值(method.getGenericReturnType())。为泛型和通配符或者为空,编译都不会通过
  2. 以列表的形式获取method的注解annotations(这个最终好像没有用到),最终才调用retrofit的callAdapter()方法,该方法又会继续调用retrofit的nextCallAdapter()方法: return nextCallAdapter(null, returnType, annotations);,由于该方法过长就不贴全部了,关键代码如下:
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,Annotation[] annotations) {
   ...
    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;
      }
    }
  ...
  }

skipPast传入的是一个空对象不用管

adapterFactories还记得吧!就是构建retrofit的时候build()方法里初始化的,而且还自动添加了一个默认的CallAdapterFactory:

 adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));

那么从nextCallAdapter()方法可以看出,返回的就是adapterFactories容器里的最后一个CallAdapterFactory对象调用get方法所创建的CallAdapter对象了。

看一下实现了CallAdapter.Factory这个接口的DefaultCallAdapterFactory是怎么写的创建方法的:

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

      @Override public <R> Call<R> adapt(Call<R> call) {
        return call;
      }
    };
  }

直接返回了匿名实现的CallAdapter<Call<?>>,其实这里就是一个适配器模式(其他调用者必须将用于网络请求的对象转换成一个Call<R>对象)

@Override public <R> Call<R> adapt(Call<R> call)这个方法的实现就是返回的一个Call实例,用于做网络请求的。

2、生成用来作网络请求的实例:OkhttpOkHttpCall<>

好了到了这里我们先不去看new MethodHandler()的其他几个参数具体是怎样初始化的,因为还记得retorfit的create()方法吗?最后一句:

 return loadMethodHandler(method)
                    .invoke(args);

现在我们loadMethodHandler(method)就告一段落了,其他的几个参数到后面在具体解析(这个方法就是用来创建MethodHandler的实例的)。接下来看一下MethodHandler的invoke(args)做了什么:

Object invoke(Object... args) {
    return callAdapter.adapt(
        new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
  }

invoke方法将已经实例化的callAdapter的adapt方法传入的 new OkHttpCall<>作为返回。

小结

现在就可以基本对Retrofit的网络请求实现原理写一个结论出来:

  1. 通过build模式创建一个Retrofit
  2. 调用创建出的retorfit的create方法(动态代理模式)创建代理对象
  3. (被代理对象是一个interfafe)所以要通过MethodHandler,使方法“合理化”(主要是解析注解和构建request,下面的分析会讲到)。
  4. 如果在构建retrofit时,没有对addCallAdapterFactory做配置就会采用默认的DefaultCallAdapterFactory生成Call适配器,那么代理对象调用方法的返回值,也就是invoke方法的返回,是通过callAdapter.adapt()的返回,其实最终就是一个继承了Call<>的OkHttpCall<>了。

例如

MyApi api = retrofit.create(MyApi.class);
 * Response<User> user = api.getUser().execute();

这里的MyApi api就是被这个生成的代理对象赋值,代理对象和被代理对象拥有同名方法getUser(),这里的这个getUser()方法返回值就是MethodHandler.invok()的返回值OkHttpCall<>了。execute()就是OkHttpCall<>里面的网络请求的方法。

四、OkHttpCall<>对象

execute()的具体实现这里先不去分析,有几个网络请求的问题先捋一捋:

  1. 网络请求方法所需要的参数怎么传进去的(其实就是args),是怎么处理这些参数的?
  2. 一个网络请求的链接怎么拼接的?
  3. 怎么判断用GET还是用POST?
  4. ...

其实这些都是通过对Annotation(注解)的解析实现的,既然最后都是用OkHttpCall<>的具体对象来做的网络请求,那这一部分就主要探寻OkHttpCall<>前世今生吧!

1、OkHttpCall<>的创建

OkHttpCall<>第一次被创建的地方就是在MethodHandler里初始化的callAdapter的adapt方法里。

new MethodHandler()所需要的4个参数除了callAdapter,其他三个参数都是用来创建OkHttpCall<>对象的,当然创建OkHttpCall<>对象也需要4个参数:

 OkHttpCall(okhttp3.Call.Factory callFactory,
                     RequestFactory requestFactory, 
                     Object[] args,
                    Converter<ResponseBody, T> responseConverter) 

args,就是通过动态代理得到的method方法里所需要的参数的一个列表,在调用MethodHandler的invoke方法时传入(参考源码或者上一章Retrofit的creat()和MethodHandler部分的代码)。
而其他的三个参数都要通过MethodHandler的静态方法 create()里传入的retorfit对象获得。以下是三个参数的初始化方式:

  1. callFactory:
retrofit.callFactory();
  1. responseConverter :
Converter<ResponseBody, ?> responseConverter =
        createResponseConverter(method, retrofit, responseType);
  1. requestFactory:
 RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);

因为OkHttpCall<>没有对method的注解做任何操作,所以method的注解的解析操作就与requestFactory或者responseConverter有关了。

callFactory:

retrofit.callFactory()返回的就是一个OkHttpClient对象,这个在构建Retrofit的章节说过。

responseConverter :

responseConverter的初始化与callAdapter的初始化类似最终调用了retrofit的nextRequestBodyConverter关键代码:

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

上面的循环也是为了取出容器里的最后一个实例。如果在构建retrofit没有设置,就会拿到默认的工厂实例。并用这个工厂实例创建一个Converter<ResponseBody, ?>的实例

当然看到这个converterFactories是不是也很熟悉呢?没错这家伙在Retrofit.Build里被初始化的同时也加入了一个默认的Converter.Factory的实例(在Retrofit.Build的构造方法里):

 public Builder() {
      // 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());
    }

好,那么我们看看这里是怎么样创建Converter<ResponseBody, ?>实例的方法:

 @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    if (type == ResponseBody.class) {
      if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
        return StreamingResponseBodyConverter.INSTANCE;
      }
      return BufferingResponseBodyConverter.INSTANCE;
    }
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

看看,这里就在对method的注解进行判断了(现在你就可以猜想一下这个Converter<ResponseBody, ?>的具体功能),通过判断的结果返回的可能有三种实例,都是单例的看一下这三种实例,内部都实现那些方法:

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

哦哦 看到这里是不是有点眼熟啊

@Override public ResponseBody convert(ResponseBody value)这个方法又是对传入的参数做了一个转换!看一下接口Converter的定义:

public interface Converter<F, T> {
  T convert(F value) throws IOException;
  ...
}

将F转为T,不过三个具体实现都是Converter<ResponseBody, ResponseBody>,所以这里有些看不懂呢,不过没关系,这个参数先到这里为止吧!不影响继续探索。

requestFactory:

在MethodHandler里requestFactory是像这样创建的

 RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);

静态方法RequestFactoryParser.parse(),那么就去看看这个类里具体是怎么创建requestFactory的吧:

static RequestFactory parse(Method method, Type responseType, Retrofit retrofit) {
    RequestFactoryParser parser = new RequestFactoryParser(method);

    Annotation[] methodAnnotations = method.getAnnotations();
    parser.parseMethodAnnotations(responseType, methodAnnotations);
    parser.parseParameters(retrofit, methodAnnotations);

    return parser.toRequestFactory(retrofit.baseUrl());
  }

首先是初始化自己,并在自己的构造方法里把传入的method全局化。在看到Annotation[]注解列表了没有?说明RequestFactoryParser这个类先对methodAnnotations进行解析,然后将解析的结果用在在toRequestFactory()方法对RequestFactory里做了对初始化:

private RequestFactory toRequestFactory(BaseUrl baseUrl) {
    return new RequestFactory(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody,
        isFormEncoded, isMultipart, requestActions);
  }

那么这个类其实最关键的作用就是解析method的注解了。有两个重要的方法也是它在静态方法里调用的那两方法:

    //对method方法注解类型做判断调用解析方法,将注解名称赋值相关全局变量,
    //如果注解的value不为空也要赋值给付给全局变量,这些全局变量就是用来创建RequestFactory的。
    parser.parseMethodAnnotations(responseType, methodAnnotations);
    //对method参数的注解做解析,将注解名称赋值相关全局变量,这些全局变量也是用来创建RequestFactory的。
    parser.parseParameters(retrofit, methodAnnotations);

这里具体是怎么解析的可以看一下源码,代码太长了就不贴了,里面涉及到了很多注解类型的判断,想了解具体的实现,看一下这个RequestFactoryParser类里面的具体实现,代码总长度也很正常500多行。就看这两个重要方法就可以了。

好了拿到所有的注解类型,以及注解的value(一般是relativeUrl,和baseUrl一起用来拼接请求链接的),就可以创建RequestFactory了。

RequestFactory

RequestFactory,从名字就可以看出,是用来创建Request的,它在RequestFactoryParser里拿到的所有参数就是用来创建Request的,这个工厂类里只有一个create方法:
核心实现就是:

 RequestBuilder requestBuilder =
        new RequestBuilder(method, baseUrl.url(), relativeUrl, headers, contentType, hasBody,
            isFormEncoded, isMultipart);
    ...
    return requestBuilder.build();

里面也是build模式创建的request,中间省略的代码,其作用我也不确定,所以暂时不写它的作用了,以后确定了再补上。

当然RequestBuilder里面为了请求体Request的构建也做了大量大操作,最终创建了Request,详细的内容只有再去撸源码了,这里我也不能说的很清楚了。

那么到这里就找到了创建OkHttpCall<>所用到的所有参数了创建也在这里结束。接下来看看OkHttpCall<>用这些参数能做些什么事情。

五、OkHttpCall<>网络请求的真实面目

还记得第三章最后写到的例子吗:

    MyApi api = retrofit.create(MyApi.class);
    Response<User> user = api.getUser().execute();

这里的MyApi api就是被这个生成的代理对象赋值,代理对象和被代理对象拥有同名方法getUser(),这里的这个getUser()方法返回值就是MethodHandler.invok()的返回值OkHttpCall<>了。execute()就是OkHttpCall<>里面的网络请求的方法。

retrofit的最后一哆嗦就是调用用我们创建的OkHttpCall<>的execute()完成网络请求。execute()方法内容就比较长涉及到的也跟构建OkHttpCall<>传入的4个参数有关。这些参数在上一章中有详细的讲解,这里就不多说了。还是贴一下execute()的部分代码看看

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

  ...
      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

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

    return parseResponse(call.execute());
  }

这里创建的okhttp3.Call 是通过createRawCall()方法创建的,先不管后面的代码,直接看看createRawCall()方法是怎么写的:

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

callFactory通过几次的传递,终于开始发挥它的作用了,一开始就知道他是一个OkHttpClient,在这里就是调用它的newCall()用来创建一个Call,这个方法需要一个Request,在上一章尾门已经知道了Request是怎么来的了。那么直接看newCall方法的内部:

return new RealCall(this, request);

返回的是RealCall,它实现了Call的接口,那么OkHttpCall的execute()方法最后返回值的时候就是解析的这个RellCall 的execute()方法的返回值。这知道怎么用OkHttp得是不是很眼熟?看一下OkHttp的使用示例代码:

String url = "https://www.baidu.com/";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
    .url(url)
    .build();
Call call = okHttpClient.newCall(request);
try {
    Response response = call.execute();
    System.out.println(response.body().string());
} catch (IOException e) {
    e.printStackTrace();
}

六、总结

从这段请求示例来看,最后总结Retrofit所做的事情就是:

  1. create生成一个我们自己写好的接口(这个接口的方法、方法里的参数都要有Retrofit对应的注解做标记)的动态代理对象。
  2. 在创建动态代理对象的过程中要对被代理对象(我们写好的接口)里的方法作合法化处理。
  3. 方法的合理化确切的说是在调用代理对象的方法(与我们写的接口里的方法同名)时开始的,也就是那个创建MethodHandler.create()开始的。
  4. 最开始是初始化CallAdapter.
  5. 然后初始化requestFactory,在这里就解析了所有的注解拼接了字段。为创建OkHttp.Requst做准备。
  6. 在合法化处理第二个步骤就是MethodHandler的invoke()方法,通过CallAdapter的adpt方法创建了OkHttpCall<>。
  7. 接下来发生的所有事情就是在这个OkHttpCall<>里了。它用到了一直没有用过的CallFactory也就是OkHttpClient创建了RealCall对象,创建这个对象时用到了requestFactory.creat()方法(这里把也是一直没有用到的args,也就是用于网络请求的参数传了过去),返回的Request对象。至此OkHttpClient已经配置全部完成!
 Retrofit retrofit = new Retrofit.Builder()
     .baseUrl("http://api.example.com")
     .addConverterFactory(GsonConverterFactory.create())
     .build();
 MyApi api = retrofit.create(MyApi.class);
 Response<User> user = api.getUser().execute();

上面这段代码中getUser(),就是那个代理对象的方法。法返回的就是OkHttpCall<>对象,同时OkHttpCall<>已经将OkHttpClient(请求的方法、参数)配置好了。最后就是调用execute()方法,其实际就是调用了OkHttpClient创建的RealCall对象的execute()方法。然后再用parseResponse()将okhttp3.Response转换成retrofit2.ResPonse作为最后网络请求的结果返回。


那具体的网路请求的实现(RealCall对象的execute()方法)就是OkHttpClient的事情了。具体的实现就要看OkHttp的源码了,这个就留在下次解析吧。

结束!

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

推荐阅读更多精彩内容