(源码篇)Retrofit源码解析

Retrofit内部如何实现接口调用

我们都知道Retrofit 是通过定义接口,然后拿到接口的实例并且调用对应的方法。我们就从使用流程开始看源码里是如何实现的。
1、首先通过 retrofit.create 方法拿到自定义的 service实例,上源码:
在这里插入图片描述

这里可以看到,通过动态代理的方式生成了自定义service 的对象。并且在调用自定义接口方法时 是执行了 1 处的方法。那么来看看loadServiceMethod 方法:
在这里插入图片描述
可以看到是在①处生出了一个ServiceMethod 对象兵返回,那么一步步看进去:
在这里插入图片描述
HttpServiceMethod.parseAnnotations:
在这里插入图片描述
这里返回了一个HttpServiceMethod 对象,所以动态代理里调用的其实就是HttpServiceMethod#invoke 方法,源码如下:
在这里插入图片描述
而OkHttpCall 则是对OkHttp的封装,调用接口的细节都在里面实现了,可以看下里面的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 {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

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

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

    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) {
          t.printStackTrace();
        }
      }

      @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) {
          t.printStackTrace();
        }
      }
    });
  }

当然,从上面我们可以看到呢 HttpServiceMethod#invoke 方法中只是把OkHttpCall 当做参数传给了 callAdapter.adapt 方法,所以真正的调用接口的时机其实是在这里面。
总结:当service 里面的接口方法时,实际是调用HttpServiceMethod.invoke 方法。

请求的类型的判断

那么调用的流程我们搞清楚了,那么说说请求的类型是在什么时候判断的。其实是在 RequestFactory 创建的时候已经判断好了。
在ServiceMethod.parseAnnotations 方法中:

RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

一步步点进去,最后会调用到RequestFactory.Builder.parseMethodAnnotation 方法:
在这里插入图片描述
可以看到这里就已经根据接口方法的注解来得到请求的类型了。

callAdapter 以及 responseConverter 的作用

其实呢有很多人可能都不明白这两个到底有什么作用,我们在初始化retrofit 的时候会有如下的代码:

在这里插入图片描述
图中的①②处就是分别添加了callAdapter 和 responseConverter 。
我就先简单说下他们的用处吧。我们定义接口的时候,可能有如下的代码:
在这里插入图片描述
那么这里的返回值是 Observable< TestStringResponse > ,其中的 Observable 是由callAdapter 来解析并且返回的,因为retrofit 默认的返回值是Call 。而尖括号里面的类型则是由responseConverter 根据responseBody 解析并返回的。
callAdapter可以理解成是返回值的适配器。
responseConverter 可以理解成是请求返回数据的转换器

1、callAdapter

那么来看看他说如何操作的。回到上面 HttpServiceMethod.parseAnnotations 方法:
在这里插入图片描述
这个方法里面①②处就分别根据调用的接口去获取了callAdapter 和 responseConverter。
①处代码如下:
在这里插入图片描述
returnType是定义的接口的返回类型,如我们上面举例的Observable< TestStringResponse > 。
annotations 是该接口的注解。
继续往下看 retrofit.callAdapter :
在这里插入图片描述
继续往下看nextResponseBodyConverter :
在这里插入图片描述
可以看到是遍历了converterFactories 这个集合,并调用集合元素中的get 方法来获取Converter 接口的实例。
converterFactories 这个呢就是适配器工厂的集合,里面的get方法是获取具体的适配器。
那么这个converterFactories 是这么来的呢?代码中可以看出,是在构造函数中赋值的,而构造函数则是在Builder.build 中调用的,如下:

在这里插入图片描述
①处的代码就新建了一个CallAdapter.Factory的集合,构造函数的参数 this.callAdapterFactories 就是我们创建Retrofit实例时调用 addCallAdapterFactory 加进来的适配器工厂。
可以看到适配器工厂里面是默认就有加入了一个工厂——platform.defaultCallAdapterFactories(callbackExecutor)。这个呢其实就是 DefaultCallAdapterFactory 的实例,我们看下他的源码:
在这里插入图片描述
responseType 方法呢后面会用到,这里先按下不表。
可以看到这个get方法里面限制了 ,只有返回值为 Call 类型的 才会返回有效的 适配器。而adapter方法中,则是将call 直接返回。
我们回顾一下adapt 方法是在哪里调用的? 是在调用我们定义的接口的时候,调用HttpServiceMethod.invoke 方法,而在该方法里面调用了callAdapter.adapt方法。

当我们添加了 rxjava 的callAdapter 时也是一样的,我们来看下RxJava2CallAdapterFactory.get方法:

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

可以看到这里同样也会判断接口方法的返回值,只有满足条件的才会返回RxJava2CallAdapter 。
继续看下RxJava2CallAdapter.adapt方法:
在这里插入图片描述
可以看到用call对象生成了 CallExecuteObservable对象,该类继承自 Observable。并且在最后返回的是一个RxJavaPlugins.onAssembly(observable),这个方法里面的返回值就是Observable 类型的,所以这就实现了由默认的call类型转成返回的Observable类型。
我们继续看下CallExecuteObservable的源码:

final class CallExecuteObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall;

  CallExecuteObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  @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();
    CallDisposable disposable = new CallDisposable(call);
    observer.onSubscribe(disposable);
    if (disposable.isDisposed()) {
      return;
    }

    boolean terminated = false;
    try {
      Response<T> response = call.execute();
      if (!disposable.isDisposed()) {
        observer.onNext(response);
      }
      if (!disposable.isDisposed()) {
        terminated = true;
        observer.onComplete();
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (terminated) {
        RxJavaPlugins.onError(t);
      } else if (!disposable.isDisposed()) {
        try {
          observer.onError(t);
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }
  }

  private static final class CallDisposable implements Disposable {
    private final Call<?> call;
    private volatile boolean disposed;

    CallDisposable(Call<?> call) {
      this.call = call;
    }

    @Override public void dispose() {
      disposed = true;
      call.cancel();
    }

    @Override public boolean isDisposed() {
      return disposed;
    }
  }
}

subscribeActual 这个方法我不是很理解是什么时候调用的,看了下源码注释中的翻译:
操作符实现(包括源和中间)应该实现这个方法来执行必要的业务逻辑并处理传入的{@link Observer}。 不需要在当前的{@code Observable}实例或{@code Observer}上调用任何插件钩子; 在调用这个方法之前,{@link #subscribe(Observer)}已经应用了所有的钩子和基本的保护措施。
不是很理解,感觉应该是订阅的时候会调用这个方法(经过测试确实是订阅之后才会触发)。
在这个方法里面调用了call.execute() ,那么之前我们就知道这里的call 其实是OkHttpCall 类型的实例,那么我们看一下它里面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());
  }

这里就是调用createRawCall 方法 创建了一个真正的请求,并且调用。

那么我们先总结一下:
当我们调用自定义的service里的接口方法时。retrofit会自动根据接口方法中定义的返回值去寻找对应的callAdapter。
然后调用callAdapter里面的adapt 方法将call类型转换为你想要的类型。

2、responseConverter

可能上面说 callAdapter 的时候有细心的同学留意到了。在CallExecuteObservable 类中,有这样一句:observer.onNext(response); 这里明明是将一个response 传到下游,但是我们平时实现订阅观察者的时候,是自定义类型的实体啊。那么我们就进一步来研究一下这个问题。

从上面我们就知道,我们在 OkHttpCall.execute 方法中呢就是返回了 parseResponse(call.execute()) 。其实这个parseResponse 方法就是将我们请求返回的body转换为我们定义的实体。我们看一下源码:

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

其中有一句:T body = responseConverter.convert(catchingBody); 这里就是将返回的的body 转为我们定义的实体。
responseConverter 在HttpServiceMethod.parseAnnotations 方法中创建的。一步步传了进来:
在这里插入图片描述
注意这里①处,调用了callAdapter.responseType方法,我在前面的图里面特意标注了一句话:比如returnType 是 cal< Bean > 那么这里返回的就是Bean。没错这里获取到的就是我们接口方法返回值尖括号里面的类型。

我们看一下 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();
    }
  }
}

可以看到这里就是用gson 将 ResponseBody 转换为我们自定义的实体。
我们继续回到OkHttpCall 中。 parseResponse 方法中虽然是将responseBody 转成了自定义的实体,但是返回值还是 Response类型的,只不过是将Response.body 设置为我们的实体对象。所以在CallExecuteObservable.subscribeActual 方法中获取到的返回值是 Response 类型的。但是我们回到RxJava2CallAdapter.adapt 方法中:
在这里插入图片描述
注意①处的 isBody ,当isBody 为true 时 ,将 responseObservable 转化为BodyObservable。isBody变量是在RxJava2CallAdapterFactory.get 方法中传进来的:
在这里插入图片描述
也就是说我们自定义接口返回值的尖括号中的类型如果不是 Response 或者 Result 的子类的话,那么isBody = true。
我们回到BodyObservable 中,看看源码:

    @Override public void onNext(Response<R> response) {
      if (response.isSuccessful()) {
        observer.onNext(response.body());
      } else {
        terminated = true;
        Throwable t = new HttpException(response);
        try {
          observer.onError(t);
        } catch (Throwable inner) {
          Exceptions.throwIfFatal(inner);
          RxJavaPlugins.onError(new CompositeException(t, inner));
        }
      }
    }

可以看到这里直接把 response.body() 传给下游,上面说过 response.body() 其实已经是我们设置过的 自定义的实体了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值