美文网首页
Retroift2.0你应该懂的源码,其实并不难

Retroift2.0你应该懂的源码,其实并不难

作者: kwbsky | 来源:发表于2019-12-02 18:04 被阅读0次

    在分析源码前,我想先问个问题。既然已经有了okhttp,为什么还要用retrofit?对于许多初学者,肯定会说因为retrofit很流行,retrofit+okhttp+rxjava是安卓网络开发的标配。如果是为了用而用,那么你很难理解一个框架的精髓。为了让同学们能更好的理解retrofit,我还是先来分析下使用retrofit的好处。
    首先定义请求方法是封装在接口中,以注解的形式来标识各种请求方法、参数等,模板化更利于书写不易出错。其次他支持rxjava,rxjava的好处不言而喻,由于okhttp默认是不支持线程切换的,而rxjava正好支持,并且各种操作符十分有用,比如合并、严格按顺序执行、铺平等。最后通过工厂模式,灵活切换call的适配器;当请求体为json字符串的时候,bean转成json字符串以及响应体转成bean的转换器的切换。当我们需要增加适配器的时候,不需要修改源码,遵循了开闭原则。
    好了,开始上源码:

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

    这里的形参service其实就是我们平时写请求方法的接口,通过动态代理返回了service的代理对象。因为本身service就是个接口,所以在invoke方法中是调用method#invoke是没有意义的。那这里用动态代理是什么作用呢?其实有点类似拦截器的效果,这里能统一处理开发者调用方法时传入的参数和定义方法时的一些注解。事实是不是如此呢?我们继续往下看。核心代码就3行。

    获取serviceMethod
    ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
    
    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;
      }
    

    serviceMethodCache是个支持并发的map,以请求方法的method对象为key保存ServiceMethod。缓存中有就返回,没有就通过builder去构建,并放入缓存。创建的代码如下:

    Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          this.methodAnnotations = method.getAnnotations();
          this.parameterTypes = method.getGenericParameterTypes();
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }
    

    methodAnnotations指方法上的注解,parameterTypes指方法所有参数的类型,parameterAnnotationsArray指方法所有参数的所有注解。
    然后看build方法:

    public ServiceMethod build() {
          callAdapter = createCallAdapter();
          responseType = callAdapter.responseType();  
          responseConverter = createResponseConverter();
           for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
    
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler<?>[parameterCount];
          for (int p = 0; p < parameterCount; p++) {
            Type parameterType = parameterTypes[p];
            if (Utils.hasUnresolvableType(parameterType)) {
              throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
                  parameterType);
            }
    
            Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
            if (parameterAnnotations == null) {
              throw parameterError(p, "No Retrofit annotation found.");
            }
    
            parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
          }
    
            return new ServiceMethod<>(this);
    }
    

    首先是获取callAdapter

    private CallAdapter<T, R> 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 {
            //noinspection unchecked
            return (CallAdapter<T, R>) 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);
          }
        }
    

    获取方法的返回值类型和所有的注解,并把他们作为参数传给retrofit#callAdapter方法

    public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
        return nextCallAdapter(null, returnType, annotations);
      }
    
    public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
          Annotation[] annotations) {
          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;
          }
        }
    }
    

    adapterFactories是个list,保存了我们添加的callAdapterFactory,然后调用get方法,传入请求方法的返回值类型和注解来返回calladapter。说着有点抽象,我们举个例子。我们平时用的时候经常会添加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, 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);
      }
    

    getRawType方法用于检查返回值的type的具体类型,我们一般写的是Observable,那么返回的就是class。再判断class的泛型,如果是response或者result就会抛异常,否则就返回RxJava2CallAdapter。因为我们的泛型是Observable,所以callAdapter就是RxJava2CallAdapter。
    responseType自然就是Observable.class。
    接下来是创建响应转换器,也就是如何把响应流转换成我们需要的bean。

    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);
          }
        }
    
    public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
        return nextResponseBodyConverter(null, type, annotations);
      }
    
    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
          @Nullable 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;
          }
        }
    }
    

    converterFactories是一个list,保存了我们设置的转换器工厂,比如我们常用的GsonConverterFactory。他里面有两个实现方法,分别返回请求体的转化器和响应体的转化器。
    接下里是解析请求方法的注解:

    private void parseMethodAnnotation(Annotation annotation) {
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
            if (!Void.class.equals(responseType)) {
              throw methodError("HEAD method must use Void as response type.");
            }
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
          } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
          } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
              throw methodError("@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
          } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
              throw methodError("Only one encoding annotation is allowed.");
            }
            isMultipart = true;
          } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
              throw methodError("Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
          }
        }
    

    这里以post为例来分析一下:

    private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
          if (this.httpMethod != null) {
            throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
                this.httpMethod, httpMethod);
          }
          this.httpMethod = httpMethod;
          this.hasBody = hasBody;
    
          if (value.isEmpty()) {
            return;
          }
    
          // Get the relative URL path and existing query string, if present.
          int question = value.indexOf('?');
          if (question != -1 && question < value.length() - 1) {
            // Ensure the query string does not have any named parameters.
            String queryParams = value.substring(question + 1);
            Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
            if (queryParamMatcher.find()) {
              throw methodError("URL query string \"%s\" must not have replace block. "
                  + "For dynamic query parameters use @Query.", queryParams);
            }
          }
    
          this.relativeUrl = value;
          this.relativeUrlParamNames = parsePathParameters(value);
        }
    

    httpMethod赋值为“POST”,hasBody赋值为true,value是post注解的值,也就是我们定义的uri,如果uri里包含‘?’就会抛异常,因为这是post方法。
    接着遍历parameterTypes,他是请求方法的所有参数类型的数组,parameterAnnotationsArray是个二维数组,他保存所有参数的所有注解。我们来看parseParameter方法,参数p是当前索引,参数parameterType是当前参数类型,parameterAnnotations是当前参数的所有注解数组。

    private ParameterHandler<?> parseParameter(
            int p, Type parameterType, Annotation[] annotations) {
          ParameterHandler<?> result = null;
          for (Annotation annotation : annotations) {
            ParameterHandler<?> annotationAction = parseParameterAnnotation(
                p, parameterType, annotations, annotation);
    
            if (annotationAction == null) {
              continue;
            }
    
            if (result != null) {
              throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
            }
    
            result = annotationAction;
          }
    
          if (result == null) {
            throw parameterError(p, "No Retrofit annotation found.");
          }
    
          return result;
        }
    

    遍历请求方法的某个参数的注解数组,调用parseParameterAnnotation方法,这个方法有点长,我就以表单提交为例来分析:

    private ParameterHandler<?> parseParameterAnnotation(
            int p, Type type, Annotation[] annotations, Annotation annotation) {
    
            else if (annotation instanceof Field) {
            if (!isFormEncoded) {
              throw parameterError(p, "@Field parameters can only be used with form encoding.");
            }
            Field field = (Field) annotation;
            String name = field.value();
            boolean encoded = field.encoded();
    
            gotField = true;
    
            Class<?> rawParameterType = Utils.getRawType(type);
            if (Iterable.class.isAssignableFrom(rawParameterType)) {
              if (!(type instanceof ParameterizedType)) {
                throw parameterError(p, rawParameterType.getSimpleName()
                    + " must include generic type (e.g., "
                    + rawParameterType.getSimpleName()
                    + "<String>)");
              }
              ParameterizedType parameterizedType = (ParameterizedType) type;
              Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
              Converter<?, String> converter =
                  retrofit.stringConverter(iterableType, annotations);
              return new ParameterHandler.Field<>(name, converter, encoded).iterable();
            } else if (rawParameterType.isArray()) {
              Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
              Converter<?, String> converter =
                  retrofit.stringConverter(arrayComponentType, annotations);
              return new ParameterHandler.Field<>(name, converter, encoded).array();
            } else {
              Converter<?, String> converter =
                  retrofit.stringConverter(type, annotations);
              return new ParameterHandler.Field<>(name, converter, encoded);
            }
    
          }
    }
    

    因为最终返回的是ParameterHandler,我们先来讲解一下他。
    ParameterHandler是个抽象类,定义了抽象方法apply,顾名思义,这个类就是用来处理参数的。打开这个类,可以发现好多静态内部类,且都是他的实现类。其实就是对应着请求参数的注解。我这里仍旧以表单提交为例来分析。

    static final class Field<T> extends ParameterHandler<T> {
        private final String name;
        private final Converter<T, String> valueConverter;
        private final boolean encoded;
    
        Field(String name, Converter<T, String> valueConverter, boolean encoded) {
          this.name = checkNotNull(name, "name == null");
          this.valueConverter = valueConverter;
          this.encoded = encoded;
        }
    
        @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
          if (value == null) return; // Skip null values.
    
          String fieldValue = valueConverter.convert(value);
          if (fieldValue == null) return; // Skip null converted values
    
          builder.addFormField(name, fieldValue, encoded);
        }
      }
    

    代码很简单,就是用一个转换器去转换参数value,并且调用RequestBuilder#addFormField把name和转换后的value存储起来。

    void addFormField(String name, String value, boolean encoded) {
        if (encoded) {
          formBuilder.addEncoded(name, value);
        } else {
          formBuilder.add(name, value);
        }
      }
    
     private @Nullable FormBody.Builder formBuilder;
    

    其实内部就是调用了okhttp的formbody来存储name和value。
    好了,我们再回到创建ParameterHandler的地方。

    else if (annotation instanceof FieldMap) {
            if (!isFormEncoded) {
              throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
            }
            Class<?> rawParameterType = Utils.getRawType(type);
            if (!Map.class.isAssignableFrom(rawParameterType)) {
              throw parameterError(p, "@FieldMap parameter type must be Map.");
            }
            Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
            if (!(mapType instanceof ParameterizedType)) {
              throw parameterError(p,
                  "Map must include generic types (e.g., Map<String, String>)");
            }
            ParameterizedType parameterizedType = (ParameterizedType) mapType;
            Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
            if (String.class != keyType) {
              throw parameterError(p, "@FieldMap keys must be of type String: " + keyType);
            }
            Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
            Converter<?, String> valueConverter =
                retrofit.stringConverter(valueType, annotations);
    
            gotField = true;
            return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded());
    
          }
    

    如果参数类型是Iterable.class的子类,但是又不是参数化类型就会抛异常,最终返回的是:

    final ParameterHandler<Iterable<T>> iterable() {
        return new ParameterHandler<Iterable<T>>() {
          @Override void apply(RequestBuilder builder, @Nullable Iterable<T> values)
              throws IOException {
            if (values == null) return; // Skip null values.
    
            for (T value : values) {
              ParameterHandler.this.apply(builder, value);
            }
          }
        };
      }
    

    代码很简单,就是遍历参数Iterable去调用当前对象的重载方法apply,因为当前对象为匿名内部类,那么ParameterHandler.this就是指外部类,也即Field对象。说白了,就是遍历Iterable去调用Field的apply方法。那么这里的转换器又是什么呢?

    public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");
    
        for (int i = 0, count = converterFactories.size(); i < count; i++) {
          Converter<?, String> converter =
              converterFactories.get(i).stringConverter(type, annotations, this);
          if (converter != null) {
            //noinspection unchecked
            return (Converter<T, String>) converter;
          }
        }
    
        // Nothing matched. Resort to default converter which just calls toString().
        //noinspection unchecked
        return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
      }
    

    stringConverter是个空实现,而我们传入的GsonConverterFactory通常不会重写这个方法,所以这里遍历converterFactories会找不到,最后会返回
    BuiltInConverters.ToStringConverter.INSTANCE。

    static final class ToStringConverter implements Converter<Object, String> {
        static final ToStringConverter INSTANCE = new ToStringConverter();
    
        @Override public String convert(Object value) {
          return value.toString();
        }
      }
    

    他是如果转换的呢?仅仅是把传入的值转为了String。
    好了,再回来看创建ParameterHandler,如果参数类型是数组,那么就返回Field#array

    final ParameterHandler<Object> array() {
        return new ParameterHandler<Object>() {
          @Override void apply(RequestBuilder builder, @Nullable Object values) throws IOException {
            if (values == null) return; // Skip null values.
    
            for (int i = 0, size = Array.getLength(values); i < size; i++) {
              //noinspection unchecked
              ParameterHandler.this.apply(builder, (T) Array.get(values, i));
            }
          }
        };
      }
    

    其实跟上面的interate方法是一样的,在此不再赘述。
    最后else就返回Field。
    再回到servicemethod#parseParameter方法,遍历注解创建ParameterHandler,如果不为空就直接返回。这也很好理解,一个请求方法的参数只能使用一种http的方法,比如我用post表单,那么参数注解就是@field,不能又是field又是query。
    至此,ServiceMethod对象就创建完成了。

    创建okhttpcall
    OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
    return serviceMethod.callAdapter.adapt(okHttpCall);
    

    这个okhttpcall又是什么呢?我们来分析他的几个方法:

    @Override public synchronized Request request() {
        okhttp3.Call call = rawCall;
        if (call != null) {
          return call.request();
        }
        if (creationFailure != null) {
          if (creationFailure instanceof IOException) {
            throw new RuntimeException("Unable to create request.", creationFailure);
          } else {
            throw (RuntimeException) creationFailure;
          }
        }
        try {
          return (rawCall = createRawCall()).request();
        } catch (RuntimeException e) {
          creationFailure = e;
          throw e;
        } catch (IOException e) {
          creationFailure = e;
          throw new RuntimeException("Unable to create request.", e);
        }
      }
    

    里面创建一个okhttp的call,并返回了对应的okhttp的request。

    private okhttp3.Call createRawCall() throws IOException {
        Request request = serviceMethod.toRequest(args);
        okhttp3.Call call = serviceMethod.callFactory.newCall(request);
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
      }
    
    Request toRequest(@Nullable Object... args) throws IOException {
        RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
            contentType, hasBody, isFormEncoded, isMultipart);
    
        @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
        ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
    
        int argumentCount = args != null ? args.length : 0;
        if (argumentCount != handlers.length) {
          throw new IllegalArgumentException("Argument count (" + argumentCount
              + ") doesn't match expected count (" + handlers.length + ")");
        }
    
        for (int p = 0; p < argumentCount; p++) {
          handlers[p].apply(requestBuilder, args[p]);
        }
    
        return requestBuilder.build();
      }
    

    创建了一个RequestBuilder,然后遍历刚才生成的ParameterHandler(每个请求方法的参数对应一个),调用apply来处理参数,最后build方法来创建okhttp的request。
    serviceMethod.callFactory其实就是我们在构建retrofit对象的时候传入的okhttpclient,由他来创建okhttp的call,这也是okhttp的标准调用。

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

    调用了okhttp的call#execute并返回okhttp的response,然后通过处理转成retrofit的response并返回:

    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;
        }
      }
    
    R toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }
    

    只有返回的状态码是200开头并且不等于204或205才算成功。
    转换器就是我们之前构建retrofit的时候传入的,比如GsonConverterFactory对应的resposebodyconverter,直接就转成了我们最终需要的bean。
    我们来看下retrofit的response持有了那些引用:

    private final okhttp3.Response rawResponse;
      private final @Nullable T body;
      private final @Nullable ResponseBody errorBody;
    

    这样就很好理解了吧,他持有okhttp的response和bean,如果是错误的情况那么bean为空,errorBody会赋值。
    好了,我做个总结,okhttpcall实际上是封装了我们直接调用okhttp的时候需要调用的那一套代码,这里由okhttpcall来帮我们完成了。

    创建observable
    return serviceMethod.callAdapter.adapt(okHttpCall);
    

    如果我们用的rxjava,那么这里的calladapter就是RxJava2CallAdapter:

    @Override public Object adapt(Call<R> call) {
        Observable<Response<R>> responseObservable = isAsync
            ? new CallEnqueueObservable<>(call)
            : new CallExecuteObservable<>(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;
      }
    

    因为isBody为true,所以就返回了BodyObservable。
    好了,retrofit的流程就梳理完了。接下来就是rxjava的事了。
    默认isAsync为false,所以创建了CallExecuteObservable,并把okhttpcall传入,然后再创建BodyObservable,把CallExecuteObservable传入。
    当最后subscribe的时候,会调用BodyObservable#subscribeActual:

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

    这个upstream就是构造函数传入的CallExecuteObservable:

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

    这里会执行retrofit#execute,返回retrofit的response,然后调用onNext方法。而这里的observer又是BodyObserver

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

    这里的observer就是我们在写网络请求的时候自己传入的observer。而response.body()正式之前转换好的bean。
    好了,我来总结一下。
    retrofit通过动态代理获取我们封装在接口里的请求方法,然后解析方法的注解,参数,参数的注解,组装成okhttp的request和call,再封装成retrofit的call(也就是okhttpcall),然后通过rxjavacalladapter,再封装成observable,最后再subscribe,就是网络请求了。是不是很简单。

    相关文章

      网友评论

          本文标题:Retroift2.0你应该懂的源码,其实并不难

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