Retrofit(三) Call

Retrofit有一个叫“Call”的抽象类,之所以会有“Call”这个名称,完全是从OKHttp借鉴过来的。因为OKHttp也有一个叫“Call”的抽象类。它们的内容是完全一样的。

OKHttp 中的"Call", 其作用是,完成对OKHttp Request的执行, 可以是异步,也可以是同步。其实现类是RealCall.java,也就是说Request的真正执行是在RealCall里面。

Retrofit 中的"Call", 其作用是, 丰富异步的执行方式。当然开发者依旧可以像使用OKHttp的Call一样使用Retrofit 中的"Call"。

Retrofit中有一个OKHttpCall类,它是Retrofit 中的"Call"的实现类。其作用是,

  • 完成对OKHttp 中的"Call"的封装,以及对OKHttp Request的填充, 包括所需要的http header, http body, http method等等。
  • 调用RealCall.java,以同步或异步的方式完成request的发送以及response的解析与反馈。

Retrofit中还有一个很重的类CallAdapter,完成对Call的转换,最后利用OKHttpCall的异步方法RealCall.enqueue(),  丰富各种异步实现的方式, 比如,RxJava,CompletableFuture 等。

 

在Call代码中,

1 . 通过Request request()方法获取到封装好的OKHtttp Request。 

2. 同步执行Request的方法, Response<T> execute() 。异步执行Request的方法, void enqueue(Callback<T> callback); 

3. 剩下的只是些辅助类。

public interface Call<T> extends Cloneable {

  Response<T> execute() throws IOException;

  void enqueue(Callback<T> callback);

  boolean isExecuted();

  boolean isCanceled();

  Request request();

  Timeout timeout();
}

下面讲解一下,利用类似OKHttp Call的方式使用Retrofit 中的"Call"。

public interface IFileTransferService {
    @POST("file/v1/initupload")
    Call<ResponseInfo<Object>>  initUpload(@HeaderMap Map<String, String> heads, @Body UploadFileInfo uploadFileInfo);
}

IFileTransferService service = mRetrofit.create(IFileTransferService.class);
        Call<ResponseInfo<Device>> response = service.initUpload(DefaultHeader, uploadFileInfo);

上面interface代码上, initUpload()方法返回的是Call<ResponseInfo<Object>>,  这个Call是Retrofit的Call。service.initUpload()也一样是Retrofit的Call。

这么做的好处是,开发者可以像使用OKHttp一样使用。

 

在Retrofit中,最后执行的是OKHttpCall。在OKHttpCall中执行OKHttp的RealCall。

final class OkHttpCall<T> implements Call<T> {
  private final RequestFactory requestFactory;
  private final Object[] args;
  private final okhttp3.Call.Factory callFactory;
  private final Converter<ResponseBody, T> responseConverter;

  @GuardedBy("this")
  private @Nullable okhttp3.Call rawCall; 
 

  @Override
  public synchronized Request request() {
      return getRawCall().request();
  }

  private okhttp3.Call getRawCall() throws IOException {
    okhttp3.Call call = rawCall;
    if (call != null) return call;

     return rawCall = createRawCall();
  }

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

    okhttp3.Call call = awCall = createRawCall();

    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            response = parseResponse(rawResponse);
            callback.onResponse(OkHttpCall.this, response);
          }

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

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

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

      call = getRawCall();
    }

    return parseResponse(call.execute());
  }

  private okhttp3.Call createRawCall() throws IOException {
    okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
    return call;
  }

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

    rawResponse =
        rawResponse
            .newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();


    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);

  }
}
  • 在OkHttpCall中有一个 rawCall。 它其实就是OKHttp的RealCall。
  • RealCall的获取是通过callFactory获取的。就是OKHttp的OkHttpClient。在Retrofit类的构造器模式里可以找到。
public Retrofit build() {
        ...
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      ...
}
  • 在 createRawCall()方法中,Request是靠requestFactory.create(args)生成的。requestFactory就是把注解表示的参数封装成Request。
  • execute() 同步执行request请求。
  • enqueue()则是异步执行请求。
  • parseResponse()解析OKHttp的Response,很重要的一点就是把OKHttp Response的body序列化成对象。T body = responseConverter.convert(catchingBody);
  • parseResponse()中还把OKHttp的Response封装成Retrofit的Response, Response.success(body, rawResponse); 额外的作用就是承载T body。

 

至于RealCall, 是OKHttp的内容,这里不做讲解。


版权声明:本文为zjuter原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。