源码分析;Retrofit处理HTTP请求主要流程

1. 写在前面

程序员界的2-8定律:80%的问题只需要使用20%的知识就可以解决,Android开发也不例外。因而,我们大部分人已经逐步变成了代码搬运工而自己却不知道。代码容易搬运,架构体系却难以复制,要成为架构师,你必须自己亲自去项目实战,读源码,研究原理。

Retrofit和OkHttp都来自于Square公司,而且都是在用来处理HTTP请求的,先来看下用OkHttp处理HTTP请求的实现:

String url = "https://api.github.com/users/octocat/repos";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
        .url(url)
        .build();
client.newCall(request).enqueue(new okhttp3.Callback() {
    @Override
    public void onFailure(okhttp3.Call call, IOException e) {

    }

    @Override
    public void onResponse(okhttp3.Call call, Response response) throws IOException {
        List<Repo> repos = JSON.parseArray(response.body().toString(), Repo.class);
    }
});

可以看到在发起HTTP请求之前需要构造Request对象,请求完成后还需要将Response转化成所需要的对象,如果每一个HTTP请求都要这么复杂,那对于需要成百上千个HTTP请求的应用来说无疑是多了很多的重复代码,对于一个追求完美的程序员来说是无法容忍的;因此Square公司推出了Retrofit框架,Retrofit的中文意思是改造,顾名思义就是在OkHttp的基础上的进行的一次升级和封装,Retrofit通过定义接口的方式来构建Request对象,通过Converter将Response转化为需要的对象,这就是Retrofit存在的意义,下面看一下通过Retrofit框架实现与上面一样的功能:

// 构建Retrofit实例,一般都是通过单例模式创建的,所以一般会创建一个Manager类来创建和管理Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        // 添加一个用来创建Converter实例的工厂,该工厂是针对于json字符串的
        .addConverterFactory(FastJsonConverterFactory.create())
        .build();

// 在一个项目中,都是会对HTTP请求进行分类的,每一个分类都会创建一个与之对应的一个接口(比如下面的GitHubService接口)
// 每一个接口包含多个方法,每一个方法对应于一个HTTP请求(执行的时候会根据方法来构建Request对象)
// 每一个方法的返回值都是一个Call对象,默认是ExecutorCallbackCall对象,针对于rxjava2就是返回的就是Observable对象
public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

// 下面就是发起HTTP的代码,相比于OkHttp来说简化了Request对象的构建和Response的解析
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(new Callback<List<Repo>>() {
    @Override
    public void onResponse(Call<List<Repo>> call, retrofit2.Response<List<Repo>> response) {
        List<Repo> repoList = response.body();
    }

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

    }
});

上面代码中提到的Call对象,其实是对OkHttp中RealCall的封装,这样的设计也体现了一种设计模式(门面模式):

门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如下:
Provide a unified interface to a set of interfaces in a subsystem.
Facade defines a higher-level interface that makes the subsystem easier to use.
(要求一个子系统的外部和内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,
使得子系统更易于使用。)

所以Retrofit示例代码中提到的Call对象就是门面模式中说到的统一的对象。
Retrofit源码地址

2. 预备知识

2.1 Java编程语言中的Type

在Retrofit中会对Method实例(对应上面的例子,就是GitHubService的listRepos方法对应的实例)进行解析,因此会对Method实例的返回值类型和参数类型进行解析,所以这里带大家了解一下Java编程语言中的Type:

扫描二维码关注公众号,回复: 9180176 查看本文章
Type是Java 编程语言中所有类型的公共高级接口,Java 编程语言中的类型包括(其中后面四种类型是泛型的三种表现形式):
1 基本类型:也就是我们所说的java中的8中基本类型。
2 原始类型(raw types):对应Class。
3 类型变量(TypeVariable):
  该接口代表各种类型变量的公共接口,如Collection<T>中的T就是一个类型变量。
  主要方法:
  Type[] getBounds():获取上边界Type数组。
4 参数化类型(ParameterizedType):
  该接口代表参数化类型,例如Collection<String>。
  主要方法:
  Type[] getActualTypeArguments():获取参数化类型中的所有类型的数组。
  Type getRawType():获取参数化类型中<>前面的类型。
5 泛型数组类型(GenericArrayType):
  该接口代表一种数组类型,其组件类型为参数化类型或类型变量
  ,例如参数化类型数组Map<String, String>[]map和类型变量数组T[] arr。
  主要方法:
  Type getGenericComponentType():返回其组件类型。

除了上面泛型的三种表现形式外还有一种并不属于Java类型的表达形式:
通配符类型(WildcardType):
该接口代表通配符类型表达式,例如 如 ?、? extends Number 或 ? super Integer.
主要方法:
Type[] getUpperBounds():获取上边界Type数组。
Type[] getLowerBounds():获取下边界Type数组。

3. 源码分析

我会根据上面的例子解析分析,因此在分析的过程中会依赖上面的代码
首先看一下Retrofit处理http请求的时序图:

3.1 构建Retrofit实例

上图中的前8步通过建造者模式构建了一个Retrofit实例

建造者模式(Builder Pattern,也叫生成器模式)的定义:
Separate the construction of a complex object from its representation so that 
the same construction process can create different representations.
(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

构建的过程也是对Retrofit实例进行初始化的过程,初始化的结果:
1> callFactory : 顾名思义是用来创建Call对象的,默认为OkHttpClient类型对象,没错,这就就是OkHttp中的OkHttpClient,通常情况下不会修改该默认值。
2> baseUrl:默认值为HttpUrl.parse("https://api.github.com/"),通常情况下在同一个项目中所有的HTTP请求URL的 protocol :// hostname[:port] 部分是相同的,即在项目中baseUrl对应的值,如果一个项目中HTTP请求URL的 protocol :// hostname[:port] 部分多余一种的话,就需要多个Retrofit对象与之对应。
3> converterFactories:顾名思义是用来保存Converter.Factory对象的容器(Converter.Factory是用来创建Converter对象的,Converter有两个常用的方法requestBodyConverter和responseBodyConverter,说到这里相信大家应该明白了Converter的作用了),默认只包含一个BuiltInConverters对象,通过第4步就可以在converterFactories集合的末尾添加一个FastJsonConverterFactory对象,这也是为什么接口的方法中@Body注解的参数是RequestBody类型时,就不会调用FastJsonRequestBodyConverter的convert方法的原因。
4> callAdapterFactories:顾名思义是用来保存CallAdapter.Factory对象的容器(CallAdapter.Factory是用来创建CallAdapter对象的,CallAdapter的adapt方法会得到Call<R>对象的代理,这里就用到了装饰者模式),默认只包含一个ExecutorCallAdapterFactory对象,通过第5步就可以在ExecutorCallAdapterFactory对象的前面插入一个RxJava2CallAdapterFactory对象。
5> callbackExecutor:顾名思义就是用来控制Retrofit示例代码中Callback执行的线程,默认值为MainThreadExecutor,即默认在主线程执行。

上面5条都是根据源码得到的,不可能在该篇文章中完全分析所有细节,只有自己亲自查阅源码才会收获更多,我只会点到为止,这样你们可以更加快速的翻阅源。

3.2 创建GitHubService接口的实例

接下来看一下第9、10步的源码:

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

可以看到使用了动态代理模式为GitHubService接口创建实例。

代理模式(Proxy Pattern)是一个使用率非常高的模式,其定义如下:
Provide a surrogate or placeholder for another object to control access to it.
(为其他对象提供一种代理以控制对这个对象的访问)

动态代理:
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。

3.3 执行GitHubService接口中的方法

第11步调用GitHubService接口中的方法,此时InvocationHandler的invoke方法被执行(即第12步),对应于上面的例子listRepos方法对应的就是invoke方法中的参数method。

3.3.1 根据Method实例构建ServiceMethod实例

第13步loadServiceMethod方法被调用,loadServiceMethod方法会根据Method实例构建与之对应的ServiceMethod实例:

  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实例的Method实例,直接将缓存中与之对应的ServiceMethod实例返回,接下来的14到33步就是根据Method实例构建ServiceMethod实例的过程:

// 第14步对应的代码
Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  // 对应与上面例子,methodAnnotations保存的时GitHubService接口的listRepos方法的注解(即@GET("users/{user}/repos"))
  this.methodAnnotations = method.getAnnotations();
  // 对应与上面例子,parameterTypes保存的是GitHubService接口中listRepos方法的所以参数的类型
  this.parameterTypes = method.getGenericParameterTypes();
  // 对应与上面例子,parameterAnnotationsArray保存的是GitHubService接口中listRepos方法的所以参数的注解
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}

// 第15对应的代码
public ServiceMethod build() {
  // 第16步到21步,完成CallAdapter实例的创建,默认为ExecutorCallAdapterFactory创建
  // 的CallAdapter实例,对于rxjava2而言对应的是RxJava2CallAdapter实例
  callAdapter = createCallAdapter();
  // 对应于上面的例子,responseType代表的是List<Repo>
  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?");
  }
  // 第22步到27步,完成 Converter<ResponseBody, T> responseConverter 实例的创建,
  // 对于fastjson而言对应的是FastJsonResponseBodyConverter实例
  // ,用于将ResponseBody中的json字符串转化成指定类型的对象
  responseConverter = createResponseConverter();

  // 第28到第30步,用于解析方法上的注解,对应于上面的例子就是对@GET("users/{user}/repos")的解析
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }

  // 方法上的注解解析完成后,httpMethod为空代表方法上没有@GET, @POST等类型的注解
  if (httpMethod == null) {
    throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
  }

  // 对于没有请求体的情况,方法上不应该有@Multipart和@FormUrlEncoded注解
  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).");
    }
  }

  // 第31、32步 完成方法参数上注解的解析,对应于上面的例子就是对@Path("user")的解析
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    // 对参数的类型进行检查,不应该包含 类型变量 和 通配符类型,具体可以参考2.1
    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);
}

3.3.2 发起http请求

  // 第35步,创建OkHttpCall实例
  OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

  // 第36步,默认情况下callAdapter代表ExecutorCallAdapterFactory创建的CallAdapter实例
  T adapt(Call<R> call) {
    return callAdapter.adapt(call);
  }

  // 第37步,返回ExecutorCallbackCall实例
  @Override public Call<Object> adapt(Call<Object> call) {
    return new ExecutorCallbackCall<>(callbackExecutor, call);
  }

  // 第39步enqueue方法发起http请求
 @Override public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "callback == null");

  // delegate是OkHttpCall实例,enqueue方法中会创建Request对象
  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);
        }
      });
    }
  });
}

4 细节分析

第3步中只是粗略的分析了Retrofit处理HTTP请求的大致流程,那么这一节就会详细分析一些关键点

4.1 CallAdapter实例的创建

第16步到21步,完成CallAdapter实例的创建,下面是Google官方对CallAdapter的adapt方法的注解:

  /**
   * Returns an instance of {@code T} which delegates to {@code call}.
   */
  T adapt(Call<R> call);

这句话也充分的说明CallAdapter是用来干嘛的了,同时也体现一种设计模式(装饰者模式),接下来看一下16步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);
  }
  // 返回值类型不能为void
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  // 获取方法上的注解,对应于上面的示例就是获取listRepos方法的注解 @GET("users/{user}/repos")
  Annotation[] annotations = method.getAnnotations();
  try {
    // 根据方法的返回值类型和注解来创建CallAdapter实例
    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw methodError(e, "Unable to create call adapter for %s", returnType);
  }
}

上面的蛛丝已经很清楚来,下面直接看第17、18步的源码:

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

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

  // 因为skipPast为null,所以start为0,
  int start = callAdapterFactories.indexOf(skipPast) + 1;
  // 默认情况下callAdapterFactories包含一个ExecutorCallAdapterFactory对象,
  // 对于RxJava2CallAdapterFactory对象,有兴趣的同学可以自己研究一下,后面的分析过程中也只会基于ExecutorCallAdapterFactory对象进行分析。
  for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
    CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
      return adapter;
    }
  }

  // 如果没有找到合适的CallAdapter实例,就会抛出IllegalArgumentException异常
  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());
}

接下来看ExecutorCallAdapterFactory的get方法,即第19步:

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
  // 如果返回值的类型不是Call类型,返回null,那么上面第18步中就会抛出IllegalArgumentException异常
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  // returnType必须是参数化类型(对应于上面的例子,returnType代表的是Call<List<Repo>>),否者会抛出IllegalArgumentException异常
  // responseType是参数化类型中的类型,对应于上面的例子,responseType代表的是List<Repo>
  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);
    }
  };
}

到这里CallAdapter实例的创建完成了,总结一下关键点:
1> 方法的返回值类型:必须是参数化类型,并且rawtype为Call类型,并且不能包含类型变量和通配符表达式,否者会抛出异常;
2> CallAdapter是用来为Call<R>创建一个代理对象T,默认情况下T是ExecutorCallbackCall类型,对应于rxjava2情况下T通常是BodyObservable类型。

4.2 Converter<ResponseBody, T>实例的创建

第22步到27步,完成 Converter<ResponseBody, T>实例的创建,接下来看一下第22步的源码:

 // 该方法返回的Converter对象是用来将ResponseBody转化成需要类型的对象,
 // 对应于上面的示例就是转化成<List<Repo>类型的对象。
private Converter<ResponseBody, T> createResponseConverter() {
  Annotation[] annotations = method.getAnnotations();
  try {
    // 第19步中提到过,对应于上面的例子,responseType代表的是List<Repo>
    // 对应于上面的例子,annotations对应于listRepos方法的注解 @GET("users/{user}/repos")
    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);
  }
}

接下来看23、24步:

public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
  return nextResponseBodyConverter(null, type, annotations);
}

public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
  checkNotNull(type, "type == null");
  checkNotNull(annotations, "annotations == null");

  // 因为skipPast为null,所以start为0
  int start = converterFactories.indexOf(skipPast) + 1;
  // 默认情况下converterFactories包含一个BuiltInConverters对象,
  // 在项目中一般都会配置一个针对于fastjson的FastJsonResponseBodyConverter对象。
  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;
    }
  }

  // 如果没有找到合适的Converter<ResponseBody, T>实例,就会抛出IllegalArgumentException异常
  StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
      .append(type)
      .append(".\n");
  if (skipPast != null) {
    builder.append("  Skipped:");
    for (int i = 0; i < start; i++) {
      builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
    }
    builder.append('\n');
  }
  builder.append("  Tried:");
  for (int i = start, count = converterFactories.size(); i < count; i++) {
    builder.append("\n   * ").append(converterFactories.get(i).getClass().getName());
  }
  throw new IllegalArgumentException(builder.toString());
}

接下来看一下25步:

// 如果方法的返回值为Call<ResponseBody>,那么BuiltInConverters的responseBodyConverter方法的返回值不会为null
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
    Retrofit retrofit) {
   if (type == ResponseBody.class) {
    return Utils.isAnnotationPresent(annotations, Streaming.class)
        ? StreamingResponseBodyConverter.INSTANCE
        : BufferingResponseBodyConverter.INSTANCE;
  }
  if (type == Void.class) {
    return VoidResponseBodyConverter.INSTANCE;
  }
  return null;
}

// 对应于上面的例子,listRepos方法的返回值不是Call<ResponseBody>类型,
// 那么FastJsonConverterFactory的responseBodyConverter方法的返回值会被使用
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                        Retrofit retrofit) {
  return new FastJsonResponseBodyConverter<>(type, mParserConfig, featureValues, features);
}

到这里Converter<ResponseBody, T>实例的创建完成了,总结一下关键点:
1> Converter<ResponseBody, T>是用来将ResponseBody对象转化成方法的返回值类型中的参数类型,对应于上面的例子,就是List<Repo>类型。
2> 如果方法的返回值为Call<ResponseBody>,那么BuiltInConverters的responseBodyConverter方法的返回值不会为null并且会被使用;否者FastJsonResponseBodyConverter对象会被使用。

4.3 OkHttpCall发起HTTP请求

OkHttpCall的enqueue方法如下:

@Override public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "callback == null");

  okhttp3.Call call;
  Throwable failure;

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

    call = rawCall;
    failure = creationFailure;
    if (call == null && failure == null) {
      try {
        // 创建OkHttp中的RealCall实例
        call = rawCall = createRawCall();
      } catch (Throwable t) {
        throwIfFatal(t);
        failure = creationFailure = t;
      }
    }
  }

  if (failure != null) {
    callback.onFailure(this, failure);
    return;
  }

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

  // 调用RealCall的enqueue方法发起HTTP请求
  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) {
        callFailure(e);
        return;
      }

      try {
        // 执行callback的onResponse方法
        callback.onResponse(OkHttpCall.this, response);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }

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

    private void callFailure(Throwable e) {
      try {
        // 执行callback的onFailure方法
        callback.onFailure(OkHttpCall.this, e);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }
  });
}

接下来看一下createRawCall和parseResponse方法:

private okhttp3.Call createRawCall() throws IOException {
  // 根据方法的参数构建Request实例,并且使用Request实例作为参数构建RealCall实例
  okhttp3.Call call = serviceMethod.toCall(args);
  if (call == null) {
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

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 {
    // 对应与上面的例子,下面这句代码会使用Converter<ResponseBody, T>实例将catchingBody转化为List<Repo>类型对象。
    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;
  }
}

到这里OkHttpCall发起HTTP请求的过程分析完了。

5 总结

到这里源码已经分析完了,Retrofit处理HTTP请求主要流程为(为了便于说明,会用到上面的例子):
1> 首先创建Retrofit实例和GitHubService接口的实例。
2> 然后调用GitHubService接口中的listRepos方法(对listRepos进行解析,得到与之对应serviceMethod对象,然后调用serviceMethod对象的adapt方法得到listRepos方法的Call<List<Repo>>类型返回值)。
3> 调用Call的enqueue方法发起请求。


 

发布了17 篇原创文章 · 获赞 0 · 访问量 174

猜你喜欢

转载自blog.csdn.net/chuhe1989/article/details/104269002