Retrofit原理解析

1,764 阅读10分钟

一、Retrofit是什么

官方介绍是这样的

A type-safe HTTP client for Android and Java. 翻译成中文是“适用于 Android 和 Java 的类型安全 HTTP 客户端。”
个人理解,Retrofit就是对OkHttp的一层封装,可以让我们更加简单的发送和解析网络请求。

二、Retrofit如何使用

详细使用建议参考官方文档,这里只作必要的介绍。
step1
首先需要创建一个类似这样的接口类

interface TestService {
    @GET("users/{user}/repos")
    fun listRepos(@Path("user") user: String): Call<List<Repo>?>
}

解释一下:
可以看到这个接口中有个抽象方法,其方法上添加了@GET注解,并且参数是字符串users/{user}/repos
其含义是: 该接口的请求方式为GET,请求的路径为baseurl+"users/{user}/repos",baseurl是retrofit创建的时候设置的,待会儿我们会讲到。

listRepos方法参数user添加了@Path注解,注解参数是字符串“user”
其含义是:将方法参数中的user变量的内容替换为@Path注解中“users/{user}/repos”{user},从而实现根据传入的user变量不同,修改path的目的。

返回值Call<List<Repo>?>Call类型,CallRetrofit中的类,表示发起请求的对象,其泛型为List<Repo>,这表示这个接口的返回内容会被封装为一个List<Repo>,其中Repo是我们自定义的数据model。

step2

private fun testRetrofit() {
    // 通过建造者模式创建Retfotit实例
    val retrofit = Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val service = retrofit.create(TestService::class.java)

    val repos = service.listRepos("hfhuaizhi")
    repos.enqueue(object : retrofit2.Callback<List<Repo>?> {

        override fun onFailure(call: Call<List<Repo>?>, t: Throwable) {
        }

        override fun onResponse(call: Call<List<Repo>?>, response: Response<List<Repo>?>) {
            Log.e(TAG, "response:${response.body()}")
        }
    })
}

step2.1
首先可以看到通过建造者模式创建了retrofit实例,其中
baseUrl("https://api.github.com"):设置设置baseUrl,其与我们在@Path注解中传入的参数组成要访问的URL,比如我们step1中的url就是“https://api.github.com/users/{user}/repos”, 其中{user}根据listRepos接口传入的user参数而改变。

addConverterFactory(GsonConverterFactory.create()):设置数据转换器,常规HTTP请求返回的是字符串文本数据,我们通过这个Convert将文本数据解析为我们想要的数据类型。比如在本例子中,“https://api.github.com/users/{user}/repos”返回的是一个json数组,我们用GsonConverter将其直接转换为数据对象。需要注意的是,GsonConverterFactory不在retrofit库中,需要额外引入com.squareup.retrofit2:converter-gson:2.9.0,类似的还有解析xml的converter等等,你也可以自定义converter。

step2.2
接下来通过我们构建出来的retrofit实例的create方法。创建了一个service,其参数是TestService::class.java 其中该方法的目的是创建一个代理的service,用动态代理生成了一个新类,待会儿我们会讲。

step2.3
调用生成的代理类的listRepos方法返回一个call对象

step2.4
调用call的enqueue方法,并在response中接收网络返回结果。

结果输出

2021-12-26 17:17:32.580 15445-15445/com.hfhuaizhi.retrofittest E/hftest: response:[Repo(archive_url=https://api.github.com/repos/hfhuaizhi/ComposeSearchDemo/{archive_format}{/ref}, archived=false, assignees_url=https://api.github.com/repos/hfhuaizhi/ComposeSearchDemo/assignees{/user}, ...省略

三、Retrofit原理解析

首先思考,我们发送一个请求的前提是什么呢,前提必然是是知道要请求的url和参数。
其中baseurl在retrofit实例的创建过程中被设置,path和参数通过接口方法的注解被设置, 所以,retrofit发起网络请求的过程就是:

通过解析接口上的方法注解,获取完整的url,然后通过OkHttp发起请求,并用converter对网络请求结果进行解析。 跟着这个思路,我们来看一下上一节step2中的方法都做了什么。

3.1 retrofit的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();
    }
    
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
      callbackExecutor = platform.defaultCallbackExecutor();
    }
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    List<Converter.Factory> converterFactories =
        new ArrayList<>(
            1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());

    return new Retrofit(
        callFactory,
        baseUrl,
        unmodifiableList(converterFactories),
        unmodifiableList(callAdapterFactories),
        callbackExecutor,
        validateEagerly);
  }
}
  • 首先对baseUrl判空,
  • 如果没设置callFactory的话,会设置一个默认的OkHttpClient,这里我们是没对callFactory设置的,所以用的是默认的OkHttpClient,有需要可以传入一个自定义OkHttpClient,设置想要的拦截器,自定义配置等等。
  • 未设置callbackExecutor的话会设置一个默认的callbackExecutor,android默认的executor是MainThreadExecutor,其内部封装了一个handler,用于将callback回调post到main thread。是的,我们retrofit2.Callback的onResponse和onFailure都是默认在主线程被回调的,而okhttp默认回调在子线程。
  • callAdapterFactories是设置callAdapter,可以设置RxJavaAdapter来配合RxJava使用,这里我们没设置callAdapter,使用默认的DefaultCallAdapterFactory
  • converterFactories 数据转换器,这里我们设置的是GsonConverter,其内部封装了Gson,用于将json字符串转换为数据对象。
  • 这些都设置完成后,返回了一个Retrofit实例

3.2 retrofit.create做了什么

总所周知,接口中的抽象方法是无法被直接调用的,所以我们要想使用listRepos方法发起网络请求,得根据我们定义的TestService接口,生成一个新的实现类,调用这个生成类的listRepos方法来发起网络请求,而retrofit.create就是来生成这个类的,其参数是要代理的类对象,这里我们传入的是TestService::class.java

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

            @Override
            public @Nullable 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);
              }
              args = args != null ? args : emptyArgs;
              return platform.isDefaultMethod(method)
                  ? platform.invokeDefaultMethod(method, service, proxy, args)
                  : loadServiceMethod(method).invoke(args);
            }
          });
}
  • 首先调用validateServiceInterface进行参数的合法性校验
  • 调用Proxy.newProxyInstance生成一个service类的代理,这里用到了java动态代理的基础知识,不太了解动态代理的同学可以先简单理解为:生成代理类的所有方法调用都会走到这个invoke回调,我们在这里invoke回调中可以获得所调用方法的注解,返回值等等各种信息,可以对方法进行hook或扩展。在这里因为我们代理的是TestService,其所有方法的返回类型都是Call,所有这里的invoke最终会return一个call对象。

3.3 service.listRepos("hfhuaizhi")做了什么

在3.2节我们知道,service是动态代理生成的TestService接口的代理对象,其listRepos方法调用后,会走到invoke回调,并返回一个call对象,所以我们接下来继续回过头看一下invoke回调做了什么

@Override
public @Nullable 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);
  }
  args = args != null ? args : emptyArgs;
  return platform.isDefaultMethod(method)
      ? platform.invokeDefaultMethod(method, service, proxy, args)
      : loadServiceMethod(method).invoke(args);
}

invoke(Object proxy, Method method, @Nullable Object[] args)参数解释:

  • proxy,代理对象实例
  • method,所调用的方法,此处是Java中的方法对象
  • args, 方法参数,一个Object数组 在invoke方法中,进行了这几步操作:
  1. 判断method在类中声明,而不是在接口中声明的话,直接调用method的invoke。
  2. 判断method是接口中的默认方法的话,走默认方法的调用,因为在java8中interface里也可以实现方法了。不是默认方法的话,调用loadServiceMethod,方法解析完成后,调用走正常的方法解析和invoke 接下来看一下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 = ServiceMethod.parseAnnotations(this, method);
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}
  • 首先从serviceMethodCache缓存中获取ServiceMethod,获取到的话就直接返回,因为对方法的解析需要通过反射获取方法上的注解,是一个相对耗时的操作,所以加一个缓存是很有必要的。
  • 没缓存该method的ServiceMethod的话,就调用ServiceMethod.parseAnnotations来解析method,生成ServiceMethod对象,并将其缓存,为了保证线程安全还加了个双重校验锁。 接下来我们有必要看一下ServiceMethod.parseAnnotations是如何通过method生成一个ServiceMethod对象的,猜测可能是通过读取method上的注解来封装成一个ServiceMethod,我们看看是不是这样(当然是这样)。
abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
    ...
}

ServiceMethod的parseAnnotations方法中又继续调用了RequestFactory.parseAnnotations,我们继续跟进去看RequestFactory.parseAnnotations方法是干嘛的。

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}

创建了一个builder,传入的参数是retrofit和method,先看Builder的构造方法,再看build方法。

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

构造方法中,接受了retrofit实例和method,并且通过method.getAnnotations()获取了method上声明的注解,并将其保存在methodAnnotations list中,获取method的参数类型保存在parameterTypes list中,获取参数注解保存在parameterAnnotationsArray list中。
接下来继续看build()方法

RequestFactory build() {
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }
  ...
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
    parameterHandlers[p] =
        parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
  }
  ...
  return new RequestFactory(this);
}

为了减少篇幅,省略了一堆不重要的方法,可以看到首先遍历刚构造方法中传入的方法注解list methodAnnotations,调用parseMethodAnnotation对其进行解析,接下来看一下parseMethodAnnotation是怎么对方法进行解析的。

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);
  } 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(method, "@Headers annotation is empty.");
    }
    headers = parseHeaders(headersToParse);
  } else if (annotation instanceof Multipart) {
    if (isFormEncoded) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isMultipart = true;
  } else if (annotation instanceof FormUrlEncoded) {
    if (isMultipart) {
      throw methodError(method, "Only one encoding annotation is allowed.");
    }
    isFormEncoded = true;
  }
}

果然不出所料,就是通过解析注解来获取请求参数,内容太多,有兴趣的可以自己去看一下。

好了我们再往回走,回到ServiceMethod的parseAnnotations方法,因为我们主要的目的还是看ServiceMethod是如何生成的。

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
    ...
}

刚RequestFactory.parseAnnotations方法我们已经知道是通过解析method上的注解来生成了一个RequestFactory,接下来又校验了一下方法返回值类型,调用HttpServiceMethod.parseAnnotations方法,传入之前解析好的requestFactory,生成了我们要使用的ServiceMethod。接下来我们继续看HttpServiceMethod.parseAnnotations方法做了什么

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  /**
   * Inspects the annotations on an interface method to construct a reusable service method that
   * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
   * method only once and reuse it.
   */
  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(
          method,
          "'"
              + getRawType(responseType).getName()
              + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }
    ...
}

这个方法很长,主要是对method方法的信息再次获取然后封装,根据方法类型返回不同的ServiceMethod
因为我们这个方法不是kotlin的suspend方法,所以最终return一个封装好的CallAdapted,loadServiceMethod就分析完毕了,继续回到代理类的invoke方法。

public @Nullable 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);
    }
    args = args != null ? args : emptyArgs;
    return platform.isDefaultMethod(method)
        ? platform.invokeDefaultMethod(method, service, proxy, args)
        : loadServiceMethod(method).invoke(args);
  }
});

loadServiceMethod后又调用了invoke,经过刚才的分析我们知道了返回的MethodService是CallAdapted,所以我们接下来看一下CallAdapted的invoke

static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
    ...
    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      return callAdapter.adapt(call);
    }
  ...
}
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
  ...
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

  protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
  ...
}

可以看到CallAdapted继承自HttpServiceMethod,HttpServiceMethod的invoke方法调用了adapt抽象方法,所以invoke方法调用后最终会调用到CallAdapted的中的adapt方法实现,并且传进去了一个参数call,是OkHttpCall。
其中调用了callAdapter的adapt方法,这个callAdapter是在CallAdapted的构造方法中传进来的,其实就是我们在3.1节所说的默认adapter DefaultCallAdapterFactory的get方法中创建的adapter

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
    ...
  @Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;
    return new CallAdapter<Object, Call<?>>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call<Object> adapt(Call<Object> call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }
  ...
}

其get方法中返回了一个匿名内部类CallAdapter,内部类的adapt方法会返回一个ExecutorCallbackCall实例,并且构造方法中传入了executor,这个executor就是3.1节所说的MainThreadExecutor,而这个call就是在HttpServiceMethod的invoke方法中new出来的OkHttpCall。
我们一开始就知道调用代理类的listRepos方法后会返回一个Call对象,这个Call的实现类就是ExecutorCallbackCall
到这里service.listRepos("hfhuaizhi")就分析结束了。

最后一步repos.enqueue做了什么

之前我们分析了一大堆,发现都是在封装参数,一直没发起真正的网络请求,那么猜测最后这一步应该就是要发起网络请求了,并回调,解析网络请求结果了吧。
由之前的分析我们知道,这个repos是ExecutorCallbackCall的实例(在我们这个例子中是这样的)。所以接下来我们去看一下ExecutorCallbackCall的enqueue方法。

static final class ExecutorCallbackCall<T> implements Call<T> {

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }
    
  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");
    delegate.enqueue(
        new Callback<T>() {
          @Override
          public void onResponse(Call<T> call, final Response<T> response) {
            callbackExecutor.execute(
                () -> {
                  if (delegate.isCanceled()) {
                    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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
          }
        });
  }
    ...
}

可以看到enqueue又调用了delegate的delegate,这个deletate在上一节中我们知道了就是HttpServiceMethod的invoke方法中new出来的OkHttpCall,所以接下来我们看一下OkHttpCall中的enqueue方法。

final class OkHttpCall<T> implements Call<T> {
    ...
  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      ...
    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }

            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @Override
          public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }

          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }
    ...
}

可以看到其内封装了一个 okhttp3.Call的call,其enqueue方法会调用OkHttp3的Call的enqueue方法来发起网络请求,并将结果通过callback回调,需要注意的是onResponse回调中的parseResponse方法,因为我们一开始就知道retrofit会直接将请求数据解析为数据model,这个解析的过程就是在此进行的,

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

  ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
  try {
    T body = responseConverter.convert(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;
  }
}

主要看responseConverter.convert(catchingBody);,这个responseConverter,就是我们一开始设置的GsonConverter,其将body转成数据model,然后将解析好的数据,回调给ExecutorCallbackCall。
我们知道okhttp3的回调是在子线程,所以继续回到ExecutorCallbackCall

delegate.enqueue(
    new Callback<T>() {
      @Override
      public void onResponse(Call<T> call, final Response<T> response) {
        callbackExecutor.execute(
            () -> {
              if (delegate.isCanceled()) {
                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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
      }
    });

可以看到其onResponse和onFailure回调中会通过callbackExecutor执行一下,我们在3.1节中知道callbackExecutor是MainThreadExecutor

private static class MainThreadExecutor implements Executor {
    final Handler mHandler = new Handler(Looper.getMainLooper());
    MainThreadExecutor() {}
    @Override
    public void execute(@NonNull Runnable command) {
        mHandler.post(command);
    }
}

其execute方法会将runnable post到主线程。至此分析结束。