美文网首页
Retrofit+OKHttp源码分析

Retrofit+OKHttp源码分析

作者: tongxiansheng | 来源:发表于2020-08-27 16:36 被阅读0次

    Retrofit

    Retrofit调用流程分析
    1.创建OkHttpClient对象,配置Intercept、网络参数等等
    2.创建Retrofit对象,配置ConverterFactoryCallAdapterFactory
    3.调用Retrofit.create(apiService)获取接口对象,这里实际返回的是一个动态代理

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

    4.获取到动态代理对象后,调用具体的方法时,可以参考上面的代码,实际调用的是serviceMethod.callAdapter.adapt(okHttpCall),这里有两个关键的对象,ServiceMethodOkHttpCall
    5.callAdapter是在创建serviceMethod时确定的,他会根据需要的返回值类型,遍历注册的CallAdapter.Factory,每个Factory中会判断该返回值类型是不是自己要处理的,如果是则返回相应的CallAdapter并且赋值给callAdapter,之后在CallAdapter中会new出需要的返回对象并返回给调用者

        public ServiceMethod build() {
          callAdapter = createCallAdapter();
          ...
        }
    
        private CallAdapter<?> createCallAdapter() {
          Type returnType = method.getGenericReturnType();
          if (Utils.hasUnresolvableType(returnType)) {
            throw methodError(
                "Method return type must not include a type variable or wildcard: %s", returnType);
          }
          if (returnType == void.class) {
            throw methodError("Service methods cannot return void.");
          }
          Annotation[] annotations = method.getAnnotations();
          try {
            return 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);
          }
        }
    
      public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }
    
      public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
        checkNotNull(returnType, "returnType == null");
        checkNotNull(annotations, "annotations == null");
    
        int start = adapterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
          CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
          if (adapter != null) {
            return adapter;
          }
        }
    
        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(adapterFactories.get(i).getClass().getName());
          }
          builder.append('\n');
        }
        builder.append("  Tried:");
        for (int i = start, count = adapterFactories.size(); i < count; i++) {
          builder.append("\n   * ").append(adapterFactories.get(i).getClass().getName());
        }
        throw new IllegalArgumentException(builder.toString());
      }
    

    6.在Retrofit中,call被包装成了OkHttpCall。在RxJava2CallAdapterFactory中,最后返回的是RxJava2CallAdapter。在adapt方法中,最后返回的是CallObservable,而CallObservable中保存了OKHttpCall的实例,所以调用者实际拿到的是CallObservable。在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();
        }
      }
    }
    
    

    7.CallObservable在最终被订阅时,开始执行请求操作。这里会调用OKHttpCallcall.execute()方法。在该方法中,会调用OKHttp中的Call类的execute方法,实现类是RealCall

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

    8.请求成功时,拿到OKHttpresponse后。在OKHttpCall中会调用parseResponse。这里最终会调用serviceMethod.toResponse(catchingBody)方法。在该方法中,会调用responseConverter.convert(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) {
          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;
        }
      }
    
      /** Builds a method return value from an HTTP response body. */
      T toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }
    

    9.上面说到的responseConvertercallAdapter一样是在ServiceMethod对象创建时确定的,根据返回类型,会遍历注册的Converter.Factory,在FactoryresponseBodyConverter方法中,会判断是否是自己要处理的,如果是,返回相应的Converter

        public ServiceMethod build() {
          callAdapter = createCallAdapter();
          responseConverter = createResponseConverter();
          ...
        }
    
        private Converter<ResponseBody, T> createResponseConverter() {
          Annotation[] annotations = method.getAnnotations();
          try {
            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);
          }
        }
    
      /**
       * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
       * {@linkplain #converterFactories() factories}.
       *
       * @throws IllegalArgumentException if no converter available for {@code type}.
       */
      public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, annotations);
      }
    
      /**
       * Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
       * {@linkplain #converterFactories() factories} except {@code skipPast}.
       *
       * @throws IllegalArgumentException if no converter available for {@code type}.
       */
      public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
          Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");
    
        int start = converterFactories.indexOf(skipPast) + 1;
        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;
          }
        }
    
        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());
      }
    

    到这里一次请求就完成了,分析了retrofit是如何处理请求和返回类型的。主要涉及CallAdapter和Converter两个类,利用动态代理巧妙的完成了对请求和返回类型转换的处理。

    OkHttp

    上面分析了Retrofit的调用流程,下面来分析一下OkHttp的调用流程。
    在上面分析的第7步,调用了OkHttp中的Call类的execute方法。

      @Override public Response execute() throws IOException {
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already Executed");
          executed = true;
        }
        captureCallStackTrace();
        try {
          client.dispatcher().executed(this);
          Response result = getResponseWithInterceptorChain();
          if (result == null) throw new IOException("Canceled");
          return result;
        } finally {
          client.dispatcher().finished(this);
        }
      }
    

    这里会调用getResponseWithInterceptorChain()执行网络请求并获取请求的Response

      Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.addAll(client.interceptors());
        interceptors.add(retryAndFollowUpInterceptor);
        interceptors.add(new BridgeInterceptor(client.cookieJar()));
        interceptors.add(new CacheInterceptor(client.internalCache()));
        interceptors.add(new ConnectInterceptor(client));
        if (!forWebSocket) {
          interceptors.addAll(client.networkInterceptors());
        }
        interceptors.add(new CallServerInterceptor(forWebSocket));
    
        Interceptor.Chain chain = new RealInterceptorChain(
            interceptors, null, null, null, 0, originalRequest);
        return chain.proceed(originalRequest);
      }
    

    在这里,会把OkHttp的一些默认的Interceptor和我们添加的一些Interceptor。最后调用RealInterceptorChainproceed方法。

      @Override public Response proceed(Request request) throws IOException {
        return proceed(request, streamAllocation, httpCodec, connection);
      }
    
      public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
          RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();
    
        calls++;
    
        // If we already have a stream, confirm that the incoming request will use it.
        if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
          throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
              + " must retain the same host and port");
        }
    
        // If we already have a stream, confirm that this is the only call to chain.proceed().
        if (this.httpCodec != null && calls > 1) {
          throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
              + " must call proceed() exactly once");
        }
    
        // Call the next interceptor in the chain.
        RealInterceptorChain next = new RealInterceptorChain(
            interceptors, streamAllocation, httpCodec, connection, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);
    
        // Confirm that the next interceptor made its required call to chain.proceed().
        if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
          throw new IllegalStateException("network interceptor " + interceptor
              + " must call proceed() exactly once");
        }
    
        // Confirm that the intercepted response isn't null.
        if (response == null) {
          throw new NullPointerException("interceptor " + interceptor + " returned null");
        }
    
        return response;
      }
    

    这里可以看到,其实就是不断的遍历interceptorsInterceptor,每次Interceptor执行proceed都会把当前的index+1。这就是OkHttp的一个主要流程了,采用了链式的方式来逐个执行。

    相关文章

      网友评论

          本文标题:Retrofit+OKHttp源码分析

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