美文网首页
Retrofit源码学习

Retrofit源码学习

作者: 写代码的 | 来源:发表于2017-05-25 15:19 被阅读60次

    基本用法

     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> 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, 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.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<T, ?> 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 + "<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, isResult, isBody, isFlowable,
            isSingle, isMaybe, false);
      }
    

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

    RxJava2CallAdapter的adapt方法

    @Override public <R> Object adapt(Call<R> call) {
        Observable<Response<R>> 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<T> extends Observable<Response<T>> {
      private final Call<T> originalCall;
    
      CallObservable(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();
        observer.onSubscribe(new CallDisposable(call));
    
        boolean terminated = false;
        try {
          Response<T> 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<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args)这个okHttpCall对象。在CallObservable的subscribeActual方法当中执行了call.execute(),这行代码返回了一个Response(注:这个Response类是Retrofit包当中的,并非OkHttp当中的)对象,那网络请求的代码应该是在这个方法中执行。

    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 {
              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<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 {
          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<T> extends Observable<T> {
      private final Observable<Response<T>> upstream;
    
      BodyObservable(Observable<Response<T>> upstream) {
        this.upstream = upstream;
      }
    
      @Override protected void subscribeActual(Observer<? super T> observer) {
        upstream.subscribe(new BodyObserver<>(observer));
      }
    
      private static class BodyObserver<R> implements Observer<Response<R>> {
        private final Observer<? super R> observer;
        private boolean terminated;
    
        BodyObserver(Observer<? super R> observer) {
          this.observer = observer;
        }
    
        @Override public void onSubscribe(Disposable disposable) {
          observer.onSubscribe(disposable);
        }
    
        @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));
            }
          }
        }
    
        @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源码学习

          本文链接:https://www.haomeiwen.com/subject/qkiozttx.html