Android 主流框架源码分析 - Retrofit源码分析

  今天我来记录一下我对Retrofit框架的理解。不得不说,Retrofit的架构设计极其优秀,既保证了使用上的方便,又高度解耦。同时Retrofit又是学习设计模式的不二典范,里面使用的设计模式数不胜数。今天我们来详细的剖析这个框架。
  本文参考资料:

  1. 这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解 )
  2. Android:手把手带你深入剖析 Retrofit 2.0 源码

  由于Retrofit里面涉及到RxJava和Gson相关知识,所以在阅读本文之前,最好是对RxJava原理有一定的了解。至于Gson,只要会用就行,其实我也不太了解Gson的原理😂。

1. 先逼逼几句

  众所周知,Retrofit是基于OkHttp设计的一个网络请求框架。其实说Retrofit是一个网络不是那么准确,准确来说,Retrofit就是OkHttp的一个外壳,Retrofit的底层网络请求使用就是OkHttp。
  同时,Retrofit完全兼容RxJava,这使得它的使用范围进一步扩大,因为这个特性,进一步促进演变近几年比较火的Android架构框架 - RxJava + Retrofit + MVP
  本文打算从Retrofit的基本使用开始,深入分析Retrofit的整个工作流程,包括线程调度、与RxJava兼容等等。

2. Retrofit组成部分

  Retrofit分为4个部分,我们来看看。

名字 含义
自定义的请求接口 主要定义一些网络请求基本参数,比如请求方式(get或者post),表单等等
由请求接口生成OkHttp的Request 根据自定义的请求接口,生成对应的可以执行的Request,此过程只要在ServiceMethod里面完成
网络请求执行器-Call 用来执行生成的Request,在Retrofit里面,使用了装饰者模式,OkHttpCall只是外壳,内部的Call才是真正执行Request
数据转换器-Converter 主要是将返回的Response解析成为我们想要的Java类对象

  提一句,Retrofit是适合于Restful API的网络请求框架,如果想要让Retrofit支持非Restful API,可以参考这一篇文章:如何使用Retrofit请求非Restful API(悄悄的给你们说一句,这个问题,我在腾讯面试被问过🙄)
  我们先大体看看Retrofit怎么通过这四个部分来进行工作。

3. 基本使用

  本文简单介绍一下Retrofit的基本使用,让大家有一个印象。但是毕竟不是初级文章,不会在方面花很多的时间。
  首先需要定义一个接口。

public interface Service {

  @POST("getSongPoetry")
  @FormUrlEncoded
  Observable<Bean> getCall(@Field("page") int page, @Field("count") int count);
}

  然后创建一个Retrofit的对象。

  private Retrofit mRetrofit = new Retrofit.Builder()
    .baseUrl("http://api.apiopen.top/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

  然后通过Retrofit的对象获得接口的代理对象。

    Service service = mRetrofit.create(Service.class);

  最后调用对应的接口来请求数据。

    service.getCall(1, 20)
      .observeOn(Schedulers.newThread())
      .subscribeOn(AndroidSchedulers.mainThread())
      .subscribe(new Observer<Bean>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Bean bean) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
      });

  整个Retrofit的网络请求过程就是这样,是不是非常的简单?这里面我们根本不需要考虑线程调度的问题,以及数据解析的问题,Retrofit已经给我们做了。

4. Retrofit

  从现在开始,我们正式开始分析Retrofit整个工作流程。我们先来看看Retrofit对象的创建。

  private Retrofit mRetrofit = new Retrofit.Builder()
    .baseUrl("http://api.apiopen.top/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

  从这里,我们已经可以看到两个设计模式--建造者模式工厂模式。当然我们也没必要紧张,就是两个的设计模式而已。
  这里通过调用Retrofit一个内部类Builder一系列的方法,进而初始化了Retrofit一些必须的对象。

(1).Builder

  我们先来看看Builder类,我们先从它的成员变量开始

    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
变量名 类型 作用
platform Platform 平台的对象,通过调用Platformget方法,可以获得适合当前环境的平台,包括Java8、Android(似乎Retrofit 2.4.0将其他的平台移除了)。Platform可以通过调用defaultCallAdapterFactory方法可以获得网络执行适配器的工厂类,调用defaultCallbackExecutor方法可以获得线程调度的对象
callFactory okhttp3.Call.Factory 网络请求执行器的工厂类,用来创建网络请求执行器的对象
baseUrl HttpUrl 网络请求的URL基地址,完整的URL地址应当是baseUrl + relativeUrl。其中,调用BuilderbaseUrl方法设置的就是基地址,在接口中@Post注解里面的值就是relativeUrl
converterFactories List<Converter.Factory> 数据转换器的数组,当收到Response时,Retrofit会根据接口里面定义的返回类型在converterFactories里面找到合适的数据转换器,从而将Response转换成为正确的类型。
callAdapterFactories List<CallAdapter.Factory> 网络请求执行适配器的数组,跟List<CallAdapter.Factory>一样,会根据接口里面定义的类型来找到合适的适配器。但是二者有所不同,待会会详细的分析。
callbackExecutor Executor 回调线程池,主要是将结果发送到指定的线程,比如,在Android平台上,肯定是将结果发送到主线程。
validateEagerly boolean 是否提前将接口里面的方法解析成为ServiceMethod。至于什么是ServiceMethod,后面会详细的解释。

  上表中详细的解释了Builder每一个成员变量的作用,在Builder类中,每一个成员变量都有一个对应的方法用来赋值。比如说addCallAdapterFactory方法可以往callAdapterFactories添加一个适配器,其他的也是如此。
  接下来我们看看Builderbuild方法。

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

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

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

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

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

      // 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());
      converterFactories.addAll(this.converterFactories);

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

  哟哟,这个build方法里面还做了不少的事情的,我们来看重点。

      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

  从这里,我们可以看出来,如果我们设置网络请求执行器,默认就是OkHttpClient,这个OkHttpClientOkHttp是一个非常核心的类,是网络请求必须的类。这里不对OkHttpClient进行展开,毕竟是OKHttp的相关知识。

      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

  同理,如果回调线程池默认也为该平台的回调线程池。比如说,如果是Android平台,那么肯定是调用这段代码:

    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

  从MainThreadExecutor的名字,我们就可以得出结果,肯定是用来回调到主线程的,毕竟在Android中,只有主线程才能更新UI🤓。
  至于其他的,都是常规的赋值,这里就不详细讲解了。
  在build方法最后一行代码,创建了一个Retrofit的对象。我们来看看Retrofit的构造方法。

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

  其实也没做什么事情,就是将Builder的成员变量对应的赋值给Retrofit

(2).Retrofit的创建为什么要使用建造者模式?

  我们发现,经过一些操作,最终的目的就是创建一个Retrofit对象,然后给Retrofit的成员变量赋值,为什么我们需要多一个Builder,然后绕一大圈来创建一个Retrofit对象呢?
  我首先问一句,在外面写这么一句代码就能创建完整的Retrofit对象,觉得爽不爽?

  private Retrofit mRetrofit = new Retrofit.Builder()
    .baseUrl("http://api.apiopen.top/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

  不用说,肯定爽,首先外部代码简洁,通过调用对应方法来给变量赋值,链式编程方格6的不行。其次,在Retrofit的构造方法也是非常的简洁,没有各种判断,所有的工作都在Builderbuild方法做了。
  所以,我们从Retrofit里面得到,如果一个对象得创建需要给很多的成员变量,不妨使用建造者模式,这使得你的代码更加的简洁。外部使用起来也是非常的简单。

(3).create方法

  从上面的栗子,我们可以知道,当创建完毕一个Retrofit的对象时,如果想要进行网络请求的话,还必须创建接口的代理对象,也就是通过调用create方法来获得一个对象。
  从我的言语之间,你们应该都知道,create方法肯定使用了代理模式,要不然何来代理对象之称。我们来看看create方法的实现。

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If 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);
          }
        });
  }

  哎呀哎呀,懵逼还是懵逼,没错!对于那些Java功底还不够牢固的同学来说,这个方法单单是看一眼就很懵逼,当初我看这个方法时,也是一脸懵逼。
  不过,懵逼归懵逼。我想说的是,这段代码是整个Retrofit的画龙点睛之笔,特别是其中的三行代码,都可以称之为神来之笔。
  我们先来粗略的看看这段代码。

    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }

  首先是validateEagerly相关的。第一行代码是验证当前这个Class对象是否合法。至于是否合法说的太笼统了,具体就是判断当前的Class是否是一个接口,并且没有继承接口。总之,就是验证Class是否一个单纯的接口。
  然后就是eagerlyValidateMethods方法的调用,如果validateEagerly为true的话,那么就调用eagerlyValidateMethods方法。至于eagerlyValidateMethods方法里面干了什么,在这里,先不急着说,等后面咱们分析ServiceMethod类时,咱们再来好好的说道说道🤓。在这里先提一句,eagerlyValidateMethods方法就是将接口的里面的方法解析成为ServiceMethod对象,这个也是validateEagerly变量的作用,之前也说过。
  看完了简单的几行代码,接下来的代码就是让人彻底懵逼的代码。说到底,其实也没啥,这里就是一个JDK的动态代理,至于不懂JDK代理的同学赶快去学习吧,这个非常的重要。
  闲话少扯,我们来看看invoke方法。前面的几个判断都没有用,在Android平台上根本不会调用,我们直接来看看最后三行代码:

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

  这三行代码,可以被整个Retrofit最核心的代码。表面上来看,只有三行代码,实际上背后给我们做的事情那是数不胜数的。我们来一行一行的看。

            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);

  这行代码的目的是将一个普通的Method转换成为ServiceMethod对象。至于怎么转换的话,还有ServiceMethod是什么,这里先不急着说,我只想说ServiceMethodRetrofit里面非常非常核心的一个类。
  我们继续来看第二行代码:

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

  这里比较好理解,就是将ServiceMethod对象包装成为一个OkHttpCall对象,这个OkHttpCall对象使用来执行网络请求的。其实它使用了装饰者模式,本身就是一个壳,这个在后面会详细解释。
  最后,我们来看看最后一行代码:

            return serviceMethod.adapt(okHttpCall);

  这里调用了ServiceMethodadapt方法。这里我们可以看看干了吗。

  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

  好吧,又调用了callAdapteradapt方法。至于adapt方法到底干了什么,这不进行展开,后面再讲解CallAdapterFactory时,会详细说到。这里,我们可以这么认为,就是通过调用了callAdapter.adapt,如果此时的CallAdapter是RxJava相关的Adapter,那么这里返回就是Observable<>之类的。
  总之,最后一行代码,就是使用适配器用来适配的。

5. ServiceMethod

  现在我们来分析一下这个核心之核心的类。我们还是先从成员变量开始。

  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  private final okhttp3.Call.Factory callFactory;
  private final CallAdapter<R, T> callAdapter;

  private final HttpUrl baseUrl;
  private final Converter<ResponseBody, R> responseConverter;
  // --------------------
  //网络请求相关参数
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  // --------------------
  private final ParameterHandler<?>[] parameterHandlers;

  哎呀,这么多我们挑几个重要分析。感觉没什么要分析,callFactorycallAdapterresponseConverter这些在都是Retrofit里面的含义都是一样的,只不过Retrofit里面是数组,这里是单个变量,表示从数组选出来的合适的,待会会详细的分析怎么选择。
  唯一值得分析的就是parameterHandlers变量,这个变量是由接口方法的每个参数解析而来的。我们看到,在接口方法里面,每一个参数都会带一些注解,这些信息都是由parameterHandlers变量来保存,并且可以根据每一个参数的特点,生成特定对象供Request的构建。这些我们在后面都会详细讲解。
  现在,我们可以回去Retrofit的eagerlyValidateMethods方法和loadServiceMethod方法。
  我们知道,当validateEagerly变量为true时,会调用eagerlyValidateMethods方法将接口中的每个方法解析成为ServiceMethod。我们先来看看:

  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

  eagerlyValidateMethods方法里面也没有做什么事,具体的操作都在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;
  }

  嗯,代码非常的简单,但是代码简单不代表容易理解。我们来具体的分析分析。
  首先是判断缓存里面是否有,如果没有的话,就根据条件创建一个ServiceMethod对象,我们看到ServiceMethod对象的创建使用的也是建造者模式。我们先来看看ServiceMethod.Builder的构造方法:

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

  相信熟悉Java的同学,这几行代码应该难不倒你们吧?前两句我就不说了,我来解释后三句。

this.methodAnnotations = method.getAnnotations();

  这行代码是获取当前方法的注解,比如说,我们在上面的getCall方法添加了@POST注解和@FormUrlEncoded注解,这里都可以获得。

this.parameterTypes = method.getGenericParameterTypes();

  这个是获取每个参数的类型。

      this.parameterAnnotationsArray = method.getParameterAnnotations();

  这个是获取每个参数的注解,就比如上面的@Field
  然后,我们再来看看ServiceMethod.Builderbuild方法。

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

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

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

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = 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);
      }

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

      return new ServiceMethod<>(this);
    }

  build方法相对来说比较长,这里我将它分为4步:

  1. 调用createCallAdapter方法,从Retrofit里面选择合适当前方法的CallAdapter
  2. 调用createResponseConverter方法,从Retrofit里面选择合适当前方法的Convert
  3. 调用parseMethodAnnotation方法,解析接口方法的注解配置。比如说,上面我们在getCall方法设置了@POST@FormUrlEncoded注解,在这一步都会被解析出来。
  4. 调用parseParameter方法将方法的每个参数解析成为ParameterHandler对象。

  我们一步一步的分析。首先来看第一步,也就是createCallAdapter方法的调用。

    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);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked
        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);
      }
    }

   createCallAdapter表达的意思非常简单,就是根据方法的返回类型和注解类型去Retrofit里面去寻找合适的CallAdapter。这里,我们先来看看RetrofitcallAdapter方法到底做了什么。

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

   callAdapter方法也是外壳,实际的工作在nextCallAdapter方法里面做的,我们来看看nextCallAdapter方法:

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

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

    StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
        .append(returnType)
        .append(".\n");
    if (skipPast != null) {
      builder.append("  Skipped:");
      for (int i = 0; i < start; i++) {
        builder.append("\n   * ").append(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());
  }

  写了那么多,归根结底就是一句话,去寻找合适的CallAdapter,如果找不到的话,就抛出异常。这里我们需要特别的注意一行代码:

      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);

  这里的意思就是去callAdapterFactories的每个元素寻找合适的CallAdapter。注意CallAdapter.Factoryget方法,后面我们在分析CallAdapter.Factory会重点的讲解它。
  这里先不对CallAdapter.Factory展开,后面会详细的分析。
  以上就是ServiceMethod.Builder的build方法第一步,也就是寻找合适CallAdapter。我们现在再来看看第二步。
  第二步是调用createResponseConverter方法,寻找合适的数据转换器。其实跟第一步差不多,我们来简单看看。
  createResponseConverter方法最终会调用到RetrofitnextResponseBodyConverter方法。在nextResponseBodyConverter方法里面,我们只需要注意一点:

      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);

  这里跟第一步的很像,同样的道理,后面我们在分析数据转换器时会详细的分析它。这里先有一个印象就行。
  第三步就是调用parseMethodAnnotation方法来解析方法的注解,这里所做目的有两点:

  1. 获取网络请求的配置参数,用以Request的构建。
  2. 验证注解是否合法。比如说,在上面的栗子中,使用POST请求,同时还每个参数还有@Field注解,所以该方法的注解必须有@FormUrlEncoded,否则会抛出异常。这些都是Retrofit的基本规则而已。

  最后,我们来看最后一步。最后一步整个4步中最复杂,代码量最多的一步。我们来详细分析分析。
  ServiceMethod通过调用parseParameter方法将每个参数解析成为ParameterHandler对象。
  而这个ParameterHandler对象到底是怎么一个东西,接下来我们会通过parseParameter方法来详细的分析。
  通过parseParameter方法的源码,我们可以看到parseParameter方法内部还是调用了parseParameterAnnotation来完成具体的解析工作。由于parseParameterAnnotation方法太特么的长了,这里我们拿一个特例来分析,就上面栗子中的@Field注解来分析:

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

  @Field注解部分还是那么的多,不过我们不用担心,我们只需要关心最后的三个return部分。为了简单起见,我们先分析最后一个return。

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

  其中第一句是去Retrofit里面去寻找合适的StringConverterStringConverter顾名思义,就是将一个对象转换成为String字符串。就比如说,上面的栗子,我们写的是int类型,而在网络请求时,提交表单时,这些数据都是String类型。这个就是StringConverter的作用。
  最后就是创建ParameterHandler.Field对象。我们先来看看这个类。

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

    Field(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) return; // Skip null values.

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

      builder.addFormField(name, fieldValue, encoded);
    }
  }

  我们在ParameterHandler时,通常来说只需要关注他的apply,因为后面ServiceMethod在构建Request是通过调用ParameterHandlerapply方法来将一个参数转换成为Request需要的数据。
  Fieldapply方法非常简单,这里就不多说了。
  而其他两个return也是比较容易,一个List数组,一个是普通数组,两者都需要遍历来转换,所以一个需要调用iterable方法,一个需要调用array方法。这里不对这两个方法做过多的解释,有兴趣的可以看看。
  到这里,ServiceMethod的基本分析也差不多,至于ServiceMethod怎么将所有的相关信息转换成为一个Resquest进行网络,怎么调用数据转换器进行数据转换,这些操作在后面我会详细的分析。
  接下来,我们来分析平台适配器--CallAdapter

6. CallAdapter

  大家还记得我们创建Retrofit对象时,通过调用Retrofit.BuilderaddCallAdapterFactory方法添加了平台适配器的工厂类吗?接下来我们会详细的分析CallAdapter.Factory,同时还有它的两个子类ExecutorCallAdapterFactoryRxJava2CallAdapterFactory
  我们先来看看CallAdapter.Factory这个抽象类:

  abstract class Factory {
    /**
     * Returns a call adapter for interface methods that return {@code returnType}, or null if it
     * cannot be handled by this factory.
     */
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    /**
     * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
     * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
     */
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    /**
     * Extract the raw class type from {@code type}. For example, the type representing
     * {@code List<? extends Runnable>} returns {@code List.class}.
     */
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }

  这只需要关注get方法,至于getParameterUpperBoundgetRawType,我相信大家都非常理解,毕竟注释写的非常清楚。
  我们在RetrofitnextCallAdapter方法里面通过调用CallAdapter.Factoryget方法来获取合适的CallAdapter,怎么判断当前的CallAdapter是否合适呢?就是看这个get方法返回的是否为null。
  具体的我们来看看ExecutorCallAdapterFactoryRxJava2CallAdapterFactory。我们先来看看那RxJava2CallAdapterFactory

(1). RxJava2CallAdapterFactory

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class<?> rawType = getRawType(returnType);

    if (rawType == Completable.class) {
      // Completable is not parameterized (which is what the rest of this method deals with) so it
      // can only be created with a single configuration.
      return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
          false, true);
    }

    boolean isFlowable = rawType == Flowable.class;
    boolean isSingle = rawType == Single.class;
    boolean isMaybe = rawType == Maybe.class;
    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }

    boolean isResult = false;
    boolean isBody = false;
    Type responseType;
    if (!(returnType instanceof ParameterizedType)) {
      String name = isFlowable ? "Flowable"
          : isSingle ? "Single"
          : isMaybe ? "Maybe" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }

    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class<?> rawObservableType = getRawType(observableType);
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
    } else if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else {
      responseType = observableType;
      isBody = true;
    }

    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

  get方法前面一系列判断,就是判断当前接口的方法是否支持RxJava适配。怎么才能表示支持RxJava呢?当然是接口方法返回的类型Observable呢。
  因为我们可以看到这个判断

    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
      return null;
    }

  如果返回类型不是Observable或者Flowable,这里都会返回null,表示当前的方法不支持RxJava。
  如果支持RxJava,最后会返回RxJava2CallAdapter的对象。我们来看看RxJava2CallAdapter,我们在分析RxJava2CallAdapter时,只需要关注adapt方法即可。

  @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

  此时跟Retrofitcreate方法就串联起来了。在Retrofitcreate方法里面,最后一行代码就是调用这里的adapt方法。
  在RxJava2CallAdapteradapt方法里面,究竟为我们做了什么?从代码中看来,其实根据情况,给我们创建了一个Observable对象。
  这里,我们还需要注意的是adapt方法的参数是一个Call对象,这个Call对象是什么,用来干嘛的?在Retrofitcreate方法里面,我们可以知道,这里的Call对象就是OkHttpCall对象,这个Call对象肯定是用来进行网络请求的。这个操作,肯定是在Observable里面。这里我们来挑一个Observable类看看。注意,接下来的分析都是跟RxJava相关的,如果不懂RxJava原理的同学,肯定感觉很吃力。
  这里我们就挑相对难一点的CallEnqueueObservable来看看。
  在看Observable的源码时,我们需要关注那个方法呢?当然是subscribeActual方法,因为最终会执行到它来,我们来看看subscribeActual方法:

  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);
  }

  整个过程的简单,熟悉RxJava和OkHttp的同学肯定感觉非常亲切,最终进行网络请求的就是最后一行代码:

    call.enqueue(callback);

  由于这里是异步的,所以需要CallBack对象来进行回调。我们来看看CallBackonResponse方法:

    @Override public void onResponse(Call<T> call, Response<T> response) {
        // 省略代码
        observer.onNext(response);
       // 省略代码
    }

  我们这里就是将网络请求返回的Response发送给订阅者。
  这个就是整个RxJava2CallAdapter的执行流程。是不是感觉RetrofitRxJava天衣无缝的结合起来了?哈哈,这就是Retrofit的魅力所在。
  至于Callenqueue方法到底做了什么,后面我会详细的分析。
  接下来我们看看ExecutorCallAdapterFactory。相信理解了RxJava2CallAdapterFactory的工作流程,ExecutorCallAdapterFactory就不会很难了。

(2). ExecutorCallAdapterFactory

  为了少说废话,这里直接看ExecutorCallAdapterFactoryget方法:

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

  在这里,我们发现它只会new了一个CallAdapter,同时实现了adapt方法。在adapt方法里面返回了一个ExecutorCallbackCall对象。接下来的ExecutorCallbackCall将Java的静态代理使用的出神入化。
  我先来简单的分析整个ExecutorCallbackCall整个结构。
  首先,如果我们在接口定义这个这种类型方法,最终会调用这个的CallAdapteradapt方法:

  @POST("getSongPoetry")
  @FormUrlEncoded
  Call<Bean> getCall(@Field("page") int page, @Field("count") int count);

  注意这里返回类型不是Observable,而是Call,这里的Call是什么的对象。我们通过Retrofitcreate方法获取一个代理对象,代理对象调用getCall方法,返回的对象在这里,既不是OKHttpCall,也不是OkHttp里面的Call对象,而是这里ExecutorCallbackCall对象。例如,调用下面的enqueue方法也是调用ExecutorCallbackCallenqueue方法:

    service.getCall(1, 20)
      .enqueue(new Callback<Bean>() {
        @Override
        public void onResponse(Call<Bean> call, Response<Bean> response) {
          
        }

        @Override
        public void onFailure(Call<Bean> call, Throwable t) {

        }
      });

  而ExecutorCallbackCall本身就是一个外壳,在ExecutorCallbackCallenqueue方法里面调用了内部的一个代理对象的enqueue方法。我们来看看:

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

  这个delegate是什么呢?它就是OkHttpCall对象。我们发现,在delegateCallback里面使用callbackExecutor将当前的数据调度到主线程去。
  至于为什么调用execute就会把当前的Response发送到主线程去,这里就不详细的解释了,有兴趣的可以看看Platfrom.Android.MainThreadExecutorexecute方法干了什么。
  CallAdapter的部分,我们的分析就到此为止,接下来我们来分析一下OkHttpCall到底做了什么。

7. 网络执行器--Call

  不论是接口返回返回类型为Observable,而在ObservablesubscribeActual方法会调用了Callenqueue方法进行网络请求;还是返回类型为Call,我们直接调用enqueue方法来进行网络请求。我们都会发现,enqueue是整个Call重中之重。
  我们先来看看Call--OkHttpCall。在Retrofit里面,这里的Call就是OkHttpCall
  跟OkHttp里面一样,这里OkHttpCall也分为同步请求和异步请求,分别对应的是execute方法和enqueue方法。我们先来一个一个的来分析。

(1). 同步请求- execute

  我们来看看execute方法的源代码:

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

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

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else if (creationFailure instanceof RuntimeException) {
          throw (RuntimeException) creationFailure;
        } else {
          throw (Error) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

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

    return parseResponse(call.execute());
  }

  整个execute方法的过程,我将它分为3步:

  1. 创建rawCall,也就是OkHttp里面的call
  2. 调用rawCallexecute方法进行真正的网络请求。
  3. 调用parseResponse方法解析Response。这里面会使用到数据转换器,这个在后面会详细的分析。

  还是按着老规矩来,一步一步的来分析。
  首先是创建rawCall对象。这一步最终是调用了ServiceMethodtoCall方法。

  okhttp3.Call toCall(@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 callFactory.newCall(requestBuilder.build());
  }

  创建rawCall对象的过程跟OkHttp里面创建一个Call是一样的,这里我们只需关注下面的代码就行了。

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

  这里调用ParameterHandlerapply方法将每个参数转换成为网络请求真正需要的数据,这里与前面我们分析parseParameter方法不谋而合。
  创建好了rawCall对象,此时就应该调用rawCallexecute方法来进行网络请求。这里的原理就是OkHttp的知识,这里就不在展开了,有兴趣的同学,可以参考我的OkHttp源码分析系列-OkHttp 源码分析系列
  最后就是调用parseResponse方法来进行数据转化。我们来简单看看parseResponse方法

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

  在parseResponse方法里面有很多的判断,这里我们不需要有太多的关注,只需要看下面这一行代码就行了:

      T body = serviceMethod.toResponse(catchingBody);

  通过调用ServiceMethodtoResponse方法将RequestBody转换成为我们需要的Bean对象。我们来看看ServiceMethodtoResponse方法。

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

  这里没有过多的操作,只是简单调用Converterconvert方法来进行数据转换。这里先不对Converter做过多的解释,待会会详细的分析它。
  整个三步执行完了,就是OKHttpCallexecute执行完毕。不得不说Retrofit的代码设计是多么的优秀,整个过程酣畅淋漓,一切都感觉合情合理的。
  接下里,我们来看看异步请求的过程。

(2). 异步请求- enqueue

  异步请求跟同步请求比较起来,只是多了一个Callback参数。而这个Callback就是我们在调用enqueue方法传入的Callback,这里就不对enqueue做过多的解释了。
  接下来,我们分析一下Retrofit最后一个部分Converter--数据转换器

8.数据转换器--Converter

  在创建Retrofit对象时,我们通过调用Retrofit.BuilderaddConverterFactory添加了一个数据转换器。我们来看看代码:

  private Retrofit mRetrofit = new Retrofit.Builder()
    .baseUrl("http://api.apiopen.top/")
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

  我们直接来看看Converter.Factory这个类:

  abstract class Factory {
    /**
     * Returns a {@link Converter} for converting an HTTP response body to {@code type}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for
     * response types such as {@code SimpleResponse} from a {@code Call<SimpleResponse>}
     * declaration.
     */
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

    /**
     * Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
     * values.
     */
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }

    /**
     * Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
     * {@code type} cannot be handled by this factory. This is used to create converters for types
     * specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
     * {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
     * {@link Query @Query}, and {@link QueryMap @QueryMap} values.
     */
    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }

    /**
     * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
     * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
     */
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    /**
     * Extract the raw class type from {@code type}. For example, the type representing
     * {@code List<? extends Runnable>} returns {@code List.class}.
     */
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }

  这里需要重点关注三个方法,一个是responseBodyConverter,另一个方法是requestBodyConverter,还有一个是stringConverter。前两个方法我们从名字上就可以知道是什么意思,一个将获取Response的转换器;一个是获取Request的转换器;stringConverter方法,我们在将每个参数解析成为ParameterHandler对象看到过,这个方法的作用主要将参数转换成为网络请求需要的配置参数。
  具体的实现,我们来看GsonConverterFactory,在这里,我们重点分析一下responseBodyConverter方法,requestBodyConverter方法跟responseBodyConverter是一样的原理。

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

  这里创建了一个GsonResponseBodyConverter对象,我们来看看这个类:

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }
}

  整个GsonResponseBodyConverter非常的简单,在ServiceMethodtoResponse方法里面,就是调用了convert方法将Responsebody转换成为我们的Bean对象。
  而我们从这里可以看出来,整个convert方法非常的简单,没有做什么难以理解的操作,实际上,所有的解析工作都是由Gson给我们完成的。从这里来看,Gson确实强大,不愧是Google爸爸的东西。这里就不对Gson做过多的解释,因为我也不懂😂。

9. 总结

  最后,我们对Retrofit做一个简单的总结。

  1. Retrofit大体上分为4个部分:接口、Request(ServiceMethod)、网络请求执行器Call、数据转换器Converter。每个部分都有自己的职责。
  2. Retrofit里面最核心的一个类就是ServiceMethod。这个类负责解析方法,生成对应的Request,转换Response。
  3. Retrofit 内部使用太多太多的设计模式,是学习设计模式的不二典范。

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

推荐阅读更多精彩内容