Source Analysis; Retrofit HTTP requests the main flow

1. EDITORIAL

2-8 Programmer's law sector: 80% of problem only need to use 20% of knowledge can be resolved, Android development is no exception. Thus, most of us have gradually become a porter while he did not know the code. Code is easy to handle, but difficult to copy the system architecture, to become an architect, you have to go and combat their own project, read the source code, study principle.

Retrofit and OkHttp are from Square Company, and are used to process the HTTP request, first look at the process implemented by the HTTP request OkHttp:

 

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

You can see before initiating a HTTP request needs to construct the Request object, the request is completed Response also need to be converted into the required target, if each HTTP request to be so complicated, that for applications requiring hundreds of HTTP request to undoubtedly say more than a lot of duplicate code, for a perfectionist programmer is intolerable; thus Square has introduced a framework Retrofit, Retrofit transformation in Chinese means, by definition is once carried out on the basis of OkHttp and upgrade packages, Retrofit constructed by way of the Request object interfaces defined by the Response Converter into a subject in need thereof, which is the meaning Retrofit exist, the following look at the implementation and above the same functionality through Retrofit framework:

 

// 构建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 object code mentioned above, in fact, is the encapsulation of OkHttp RealCall, this design embodies a design pattern (Facade Mode):

 

门面模式(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.
(要求一个子系统的外部和内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,
使得子系统更易于使用。)

So Call object Retrofit sample code that is mentioned in the unified object model when it comes to the facade.
Retrofit Source Address

2. Preliminaries

2.1 Java programming language Type

In the Method instance will Retrofit (corresponding to the above example, it is an example of a method GitHubService corresponding listRepos) parsing, so Method instance will return type and parameter types parsing, so here we look with the Java programming language the Type:

 

 

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. source code analysis

I will be based on the example above analytical analysis, so the process will depend on the analysis of the above code
first look at the timing diagrams Retrofit processing http request:

3.1 build Retrofit examples

Step before the above figure 8 constructed by an instance of the builder pattern Retrofit

 

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

The build process is also Retrofit instance initialization process, initialization of results:
1> callFactory : As the name suggests is used to create Call object, the default is OkHttpClient type object, yes, this is OkHttp in OkHttpClient, usually without modifies the default value.
2> the baseUrl : default value HttpUrl.parse ( " https://api.github.com/ "), usually all in the same project in the HTTP request URL protocol: // hostname [: port] section is the same, i.e., a value corresponding baseUrl in the project, a project, if the URL of the HTTP request protocol: // hostname [: port] section superfluous one, then we need more Retrofit corresponding object.
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

Guess you like

Origin blog.csdn.net/chuhe1989/article/details/104269002