Retrofit源码学习

基本用法

 Retrofit retrofit =new Retrofit.Builder().client(okhttpClient).baseUrl("http://localhost/").addCallAdapterFactory(RxJava2CallAdapterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();
 API api=retrofit.create(API.class);
        

上面代码主要创建了Retrofit对象,并且为Retrofit对象分别设置了OkhttpClient对象、baseUrl、CallAdapterFactory对象和ConvertFactory对象。最关键的是create方法

create方法分析

 public  T create(final Class 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, 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 serviceMethod =
                (ServiceMethod) loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

以上是create方法的全部代码,只有几十行,看着也不是特别复杂。第一行 Utils.validateServiceInterface(service);从名字就可以知道是用来检验参数service是否是一个接口的,不是重点,不需要重点关注。第二行validateEagerly默认是false,所以第三行不会执行,(注:如果我们在构建Retrofit对象时设置了validateEagerly属性为true,那么第三行eagerlyValidateMethods(service)会执行,这个方法中会遍历接口中所有的方法,如果不是default方法,就调用loadServiceMethod方法,将接口中的所有方法缓存,default方法是jdk1.8当中引入的,在jdk1.8当中接口可以有实现方法,只要在方法前加default关键字)。在create方法的第五行就直接返回了一个动态代理对象,也就是说create方法实际就做了两件事,第一、验证参数是不是接口类型,第二、返回代理对象。那么重点关注的代码都在代理对象里面了。Proxy.newProxyInstance方法返回一个实现了参数service接口的对象,也就是开头 API api=retrofit.create(API.class)中的api对象。根据动态代理的特性,我们每次调用api这个对象的方法,其实调用的是InvocationHandler当中的invoke方法,也就是create方法当中第七行的new InvocationHandler()对象中的invoke方法。在invoke方法当中首先验证了方法是否是Object的方法,如果是,就直接调用并返回了。然后判断方法是否是默认方法,如果是,也直接返回了。那么重点就在最后四行代码当中了。

loadServiceMehod方法分析

在create方法的倒数第四行调用了Retrofit的loadServiceMethod方法,该方法传入method参数返回了一个ServiceMethod对象。下面是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 = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

这个方法也很简单,首先判断缓存当中有没有method对应的ServiceMethod对象,如果有就返回该对象,没有就创建对象并将其放入缓存。在构建ServiceMethod对象时传入了retrofit对象和method对象。

创建OkHttpCall对象

 OkHttpCall(ServiceMethod serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

OkHttpCall对象的构造方法很简单,仅仅是对两个属性赋值而已。到目前为止还没有看到一行关于网络请求的代码,那么网络请求的代码应该是在create方法最后一行当中了。

CallAdapter的adapt方法

在Retrofit的create方法最后一行调用了ServiceMethod的callAdapter的adapt方法。ServiceMethod的CallAdapter对象是通过Retrofit中设置的CallAdapterFactoty对象创建出来的,我设置的是RxJava2CallAdapterFactory,那主要的网络请求逻辑应该是在RxJava2CallAdapterFactory里面了。

RxJava2CallAdapterFactory的get方法

@Override
  public 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, 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" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + " or " + name + "");
    }

    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 or Response");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
    } else if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result or Result");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else {
      responseType = observableType;
      isBody = true;
    }

    return new RxJava2CallAdapter(responseType, scheduler, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

该方法返回一个CallAdapter对象,也就是ServiceMethod中的CallAdapter对象。首先分析一下该对象的创建过程。该方法首先判断我们调用的接口方法的返回值类型,返回值类型必须是Completable,Observable,Flowable,Single,Maybe中的一种,否则会返回null。判断完返回类型接着判断返回类型的泛型,最后返回一个RxJava2CallAdapter对象。

RxJava2CallAdapter的adapt方法

@Override public  Object adapt(Call call) {
    Observable> responseObservable = new CallObservable<>(call);

    Observable observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

这个方法主要根据接口方法返回值的类型和泛型类型返回不同的Observable,如果返回值泛型是Result类型,返回ResultObservable,如果是返回值泛型是Response类型,返回responseObservable,如果是自定义的类型则返回BodyObservable。到目前为止还是没有发现网络请求相关的代码,那么网络请求的代码应该是在Observable里面了。平时请求一般都是自定义类型,那么主要看一下Observable当中的逻辑。

CallObservable

final class CallObservable extends Observable> {
  private final Call originalCall;

  CallObservable(Call originalCall) {
    this.originalCall = originalCall;
  }

  @Override protected void subscribeActual(Observer> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call call = originalCall.clone();
    observer.onSubscribe(new CallDisposable(call));

    boolean terminated = false;
    try {
      Response response = call.execute();
      if (!call.isCanceled()) {
        observer.onNext(response);
      }
      if (!call.isCanceled()) {
        terminated = true;
        observer.onComplete();
      }
    } catch (Throwable t) {
      Exceptions.throwIfFatal(t);
      if (terminated) {
        RxJavaPlugins.onError(t);
      } else if (!call.isCanceled()) {
        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;

    CallDisposable(Call call) {
      this.call = call;
    }

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

    @Override public boolean isDisposed() {
      return call.isCanceled();
    }
  }
}

CallObservable中有一个Call对象的引用,这个对象就是在Retrofit的create方法当中的 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args)这个okHttpCall对象。在CallObservable的subscribeActual方法当中执行了call.execute(),这行代码返回了一个Response(注:这个Response类是Retrofit包当中的,并非OkHttp当中的)对象,那网络请求的代码应该是在这个方法中执行。

OkHttpCall的execute方法

@Override public Response 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 {
          throw (RuntimeException) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

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

    return parseResponse(call.execute());
  }

这个方法的逻辑很简单,首先创建一个okhttp3.Call对象,然后执行call.execute方法,最后将okhttp当中的Response类型转换为Retrofit当中的Response对象。

OkHttpCall的parseResponse方法

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

这个方法的主要逻辑就是根据不同的http响应码返回不同的Retrofit.Response。如果是正常的200响应码,会走最后这个return语句。返回一个Retrofit.Response对象,该对象封装了一个泛型类型的body和一个OkHttp.Response对象,这个泛型对象时通过ServiceMethod的toResponse方法返回的,在toResponse方法当中会调用Converter的convert方法,也就是在创建Retrofit的时候设置的ConvertFactory创建出来的Convert,通常是设置GsonConvert,也就是将网络请求的响应体解析成接口方法泛型里面的类型。

BodyObservable

final class BodyObservable extends Observable {
  private final Observable> upstream;

  BodyObservable(Observable> upstream) {
    this.upstream = upstream;
  }

  @Override protected void subscribeActual(Observer observer) {
    upstream.subscribe(new BodyObserver<>(observer));
  }

  private static class BodyObserver implements Observer> {
    private final Observer observer;
    private boolean terminated;

    BodyObserver(Observer observer) {
      this.observer = observer;
    }

    @Override public void onSubscribe(Disposable disposable) {
      observer.onSubscribe(disposable);
    }

    @Override public void onNext(Response 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));
        }
      }
    }

    @Override public void onComplete() {
      if (!terminated) {
        observer.onComplete();
      }
    }

    @Override public void onError(Throwable throwable) {
      if (!terminated) {
        observer.onError(throwable);
      } else {
        // This should never happen! onNext handles and forwards errors automatically.
        Throwable broken = new AssertionError(
            "This should never happen! Report as a bug with the full stacktrace.");
        //noinspection UnnecessaryInitCause Two-arg AssertionError constructor is 1.7+ only.
        broken.initCause(throwable);
        RxJavaPlugins.onError(broken);
      }
    }
  }
}

前面这些网络请求,响应解析功能都是在CallObservable当中完成的,但最终返回给我们用的却是BodyObservable,BodyObservable对CallObservable做了一次封装,onNext只传了Retrofit.Response的body对象,也就时Gson解析出来的对象。这样就只能得到响应体,某些时候需要用到响应头,可以将接口方法的返回值的泛型使用Retrofit.Response就可以了。

总结

1.创建Retrofit对象。
2.调用Retrofit对象的create方法返回动态代理对象。
3.调用动态代理对象的方法。
4.调用CallAdapter的adapt方法,返回一个Observable对象。
5.在Observable对象subscribe方法当中进行网络请求和响应体的解析。
(注:省略了根据接口方法注解生成Request部分)

你可能感兴趣的:(Retrofit源码学习)