查看原文
其他

Retrofit 枯燥无趣的源码分析

推荐关注↓

摘要

通过分析Retrofit源码,了解这款简洁的网络库如何提高我们的工作效率。通过动态代理技术,创建我们接口对象,以提供我们调用接口函数。通过解析接口定义的函数,装配成OkHttp网络请求所需的数据并发起网络请求。我们可以根据自己的需求,自定义请求适配器和响应转换器。

流程分析

动态代理

我们定义了service接口,并通过retrofit对象的create函数创建了service类型的对象。通过该对象,我们可以调用在service接口定义的函数,从而发起定义的网络请求。

val service=retrofit.create(service::class.java)

Retrofit通过动态代理技术生成我们定义service接口代理对象,因此调用代理对象的函数时都会转发到InvocationHandler对象的invoke函数。

  public <T> T create(final Class<T> service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class<?>[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
                  throws Throwable 
{
                //判断是否Obect的默认方法
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                //判断是否特定平台的方法,例如Android
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

loadServiceMethod

invoke函数,我们只关心loadServiceMethod(method).invoke(args)函数。loadServiceMethod(method)函数会返回一个ServiceMethod对象,ServiceMethod是一个抽象类,唯一直接实现类是HttpServiceMethod。也就是说这里调用了HttpServiceMethod.invoke(args)

  ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != nullreturn result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

loadServiceMethod函数主要先通过缓存serviceMethodCache获取ServiceMethod对象,如果缓存中没有获取到ServiceMethod对象,则通过ServiceMethod.parseAnnotations解析获取ServiceMethod对象,并将其放在缓存中。serviceMethodCache是一个ConcurrentHashMap,以MethodKey,ServiceMethodvalueServiceMethod.parseAnnotations(this, method)主要是解析Method对象(我们定义的方法)的注解,参数及注解以及返回类型,然后通过HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)生成ServerMethod对象。

ServiceMethod.parseAnnotations

该函数分别调用了RequestFactory类和HttpServiceMethodparseAnnotations函数。RequestFactory类主要封装本次网络请求的大多数信息,例如methodheaders,httpMethod等等。HttpServiceMethodServerMethod的子类,主要用来创建请求适配器和数据转换器。

  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //解析方法的注解和参数的注解及值
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
  //解析方法的注解和参数的注解及返回值
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

RequestFactory.parseAnnotations

RequestFactory.parseAnnotations(retrofit, method)通过构建者模式创建RequestFactory对象。构建的过程主要是解析传递进来的参数method对象上相关信息,并赋值到RequestFactory对象相关属性上。Method对象代表着反射上的一个函数,包含这个该函数的相关信息,例如注解,参数,返回类型等。

static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
 return new Builder(retrofit, method).build();
}

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

RequestFactory build() {
  //1、解析方法上注解
  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);
  }
  ......
  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
      //解析函数参数,包括其注解和值
      parameterHandlers[p] =
        parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
  }
  ......
  return new RequestFactory(this);
}

build函数主要解析方法上的注解,参数注解。parseMethodAnnotation(annotation)用来解析方法的注解,根据anotation的类型,例如GETPOST等等,然后根据这些方法类型在HTTP报文对应的特性,设置相关属性,例如GET类型的请求没有请求体hasBody=false,POST类型的hasBody=true

通过parseParameter解析函数参数注解和获取对应的值。参数注解的解析和函数注解的解析类似,主要检查我们使用方式是否正确和设置相关属性。并且也会判断当前函数是否Kotlin协程中的挂起函数(后文分析)。

HttpServiceMethod.parseAnnotations

HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)又是干了什么呢?将上面解析生成的RequestFactory,生成请求适配器CallAdapter和响应转换器Converter,然后将三者封装到HttpServiceMethod的子类并返回。

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) 
{
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {//是否支持协程
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType(); //获取方法的返回类型
    }
 //遍历Retrofit的CallAdapter列表,寻找是否有符合处理该adapterType的CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
 
      ......
        
 //遍历Retrofit的转换器列表,寻找合适的转换器
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);//非协程情况下,HtttpServerMethod的子类
    } else if (continuationWantsResponse) {
      //使用了协程,且返回类型Response
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //使用了协程,且返回类型ResponseBody
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

在创建CallAdatperConverter后,根据是否协程,返回不同的HttpServiceMethod子类。

createCallAdapter

其中createCallAdapter(retrofit, method, adapterType, annotations);创建CallAdapted对象。

  private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) 
{
    try {
      //noinspection unchecked
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }

调用retrofit.callAdapter(returnType, annotations),根据返回类型retrunType选择合适的请求适配器。需要注意到的是,这里是从头开始遍历,如果前面适配器符合条件,意味着会被优先选用。

  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 = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
 ......
  }

nextCallAdapter函数主要通过循环遍历在构建Retrofit是保存在callAdapterFactories列表的CallAdapter,通过其get函数查看是否匹配。如果Android SDK_INT>=24返回的是CompletableFutureCallAdapterFactory,否则返回的是DefaultCallAdapterFactory

看看CompletableFutureCallAdapterFactory对象的get函数。

 @Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != CompletableFuture.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalStateException(
          "CompletableFuture return type must be parameterized"
              + " as CompletableFuture<Foo> or CompletableFuture<? extends Foo>");
    }
    Type innerType = getParameterUpperBound(0, (ParameterizedType) returnType);

    if (getRawType(innerType) != Response.class) {
      // Generic type is not Response<T>. Use it for body-only adapter.
      return new BodyCallAdapter<>(innerType);
    }

    // Generic type is Response<T>. Extract T and create the Response version of the adapter.
    if (!(innerType instanceof ParameterizedType)) {
      throw new IllegalStateException(
          "Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>");
    }
    Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);
    return new ResponseCallAdapter<>(responseType);
  }

CompletableFutureCallAdapterFactoryget函数根据函数返回类型是否与自己要处理的返回类型一致,不一致则返回null,表示不处理,例如这里是CompletableFuture。然后进一步检查返回值的合法性,例如是不是泛型对象。最终根据泛型对象最外层类型返回CallAdapter的子类BodyCallAdapterResponseCallAdapter。两者的主要区别是其adapt函数。

//BodyCallAdapter   
@Override
public CompletableFuture<R> adapt(final Call<R> call) {
  CompletableFuture<R> future = new CallCancelCompletableFuture<>(call);
  call.enqueue(new BodyCallback(future));
  return future;
}
//ResponseCallAdapter
public CompletableFuture<Response<R>> adapt(final Call<R> call) {
  CompletableFuture<Response<R>> future = new CallCancelCompletableFuture<>(call);
  call.enqueue(new ResponseCallback(future));
  return future;
}

loadServiceMethod(method).invoke(args)

回到loadServiceMethod(method).invoke(args),也就是说,这里实际调用了CallAdapter对象的invoke函数。

@Override
final @Nullable ReturnT invoke(Object[] args) {
 Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory,      responseConverter);
 return adapt(call, args);
}

invoke函数主要是构建OkHttpCall并调用adapt函数。这里分析ResponseCallAdapteradapt函数。

@Override
public CompletableFuture<Response<R>> adapt(final Call<R> call) {
  CompletableFuture<Response<R>> future = new CallCancelCompletableFuture<>(call);
  call.enqueue(new ResponseCallback(future));
  return future;
}

网络请求

adapt函数调用了OkHttpCallenqueue函数。是不是跟OKHttp的异步请求很相似。

  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @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) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }

通过enqueue函数的简单分析,就是创建OkHttpCall对象,并调用enqueue函数。然后发起网络请求,请求成功之后调用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);
    }

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

createResponseConverter

重点地方就是在函数最后的地方调用了T body = responseConverter.convert(catchingBody);将原始数据转化成我们需要的数据类型。在HttpServiceMethodparseAnnotations函数中createResponseConverter创建响应数据转换器。

  private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) 
{
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, 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) 
{
    ......
    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;
      }
    }
 ......
  }

响应转换器与请求适配器的创建过程很相似。在创建Retrofit对象时,会将相关转化器保存到converterFactories列表,通过转化器的responseBodyConverter函数判断是否处理该响应数据。这里看下OptionalConverterFactory

final class OptionalConverterFactory extends Converter.Factory {
  static final Converter.Factory INSTANCE = new OptionalConverterFactory();

  @Override
  public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(type) != Optional.class) {
      return null;
    }

    Type innerType = getParameterUpperBound(0, (ParameterizedType) type);
    Converter<ResponseBody, Object> delegate =
        retrofit.responseBodyConverter(innerType, annotations);
    return new OptionalConverter<>(delegate);
  }

  @IgnoreJRERequirement
  static final class OptionalConverter<T> implements Converter<ResponseBody, Optional<T>> {
    final Converter<ResponseBody, T> delegate;

    OptionalConverter(Converter<ResponseBody, T> delegate) {
      this.delegate = delegate;
    }

    @Override
    public Optional<T> convert(ResponseBody value) throws IOException {
      return Optional.ofNullable(delegate.convert(value));
    }
  }
}

responseBodyConverter逻辑很简单,判断放回类型Type是不是Optional.class,然后返回OptionalConverter。那么网络成功返回数据就会调用convert函数,而这个直接委托给下一个转化器。

而在构建converterFactories列表的时候,会优先添加BuiltInConverters,然后是我们自定义的转换器,最后如果Android SDK>=24,才添加OptionalConverterFactory。也就是说从这里可以看到优先权。

而构建callAdapterFactories列表,则是先我们自定义的,再是平台默认的适配器。

通常情况下,我们都会添加GsonConverterFactory适配器,将gson转化成对象类型。

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

GsonResponseBodyConverterconvert函数。

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

到这里,Retrofit整个源码流程就分析完了。所以也应该学会了如何自定适配器和转换器了。

协程

Retrofit在目前版本2.6.0开始就已经支持协程,即允许在接口中定义挂起函数。那Retrofit如何确定接口定义的函数是挂起函数呢?

在上一节分析RequestFactory.parseAnotations中分析函数注解,说到parseParameter解析函数参数注解,有提到判断函数是否挂起函数。来看是如何判断的。

    private @Nullable ParameterHandler<?> parseParameter(
        int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
   ······
      if (result == null) {//参数没有注解
        if (allowContinuation) {//参数为函数最后一个参数
          try {
            if (Utils.getRawType(parameterType) == Continuation.class) {//参数类型为Continuation
              isKotlinSuspendFunction = true;
              return null;
            }
          } catch (NoClassDefFoundError ignored) {
          }
        }
        throw parameterError(method, p, "No Retrofit annotation found.");
      }

      return result;
    }

判断是否协程函数有三个条件:

  1. 函数参数没有注解
  2. 该参数是在函数中的最后一个位置
  3. 该参数的类型是Continuation.class

但这跟我们理解中协程的挂起函数区别有点大啊。因为这是我们理解中的Kotlin挂起函数,当它编译后成Java字节码后,会自动在函数最后一个参数增加Continuation类型的参数。

Kotlin函数

suspend fun getData()

Java函数

void getData(Continuation c)

通过解析接口中函数的最后一个参数没有注解,而且类型为Continuation时,就确定为了一个Kotlin协程挂起函数,并将ReqeustFactoryisKotlinSuspendFunction设置为true

HttpServiceMethod.parseAnnotations解析时根据isKotlinSuspendFunction来走不同的分支,例如isKotlinSuspendFunction=true情况下,返回的是SuspendForResponse,=false情况下,返回的是CallAdapter。看看具体处理了哪些工作。

  static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) 
{
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
      //协程情况下,与非协程情况下类似,获取返回类型adapterType,用于创建CallAdapter
      if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType =
          Utils.getParameterLowerBound(
              0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();//非协程情况
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    
    ......
        
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {//非协程情况
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      ////使用了协程,且返回类型Response
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      ////使用了协程,且返回类型ResponseBody
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
  }

在这里根据接口的函数返回类型的不同,返回SuspendForResponse或者SuspendForBody

  static final class SuspendForResponse<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;

    SuspendForResponse(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter<ResponseBody, ResponseT> responseConverter,
        CallAdapter<ResponseT, Call<ResponseT>> callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);

      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<Response<ResponseT>> continuation =
          (Continuation<Response<ResponseT>>) args[args.length - 1];

      // See SuspendForBody for explanation about this try/catch.
      try {
        return KotlinExtensions.awaitResponse(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.suspendAndThrow(e, continuation);
      }
    }
  }

通过调用OkHttpCall扩展函数来实现网络请求。我们知道非协程下是通过创建OkHttpCall来实现的。

suspend fun <T : Any> Call<T>.await(): T {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel()
    }
    enqueue(object : Callback<T> {
      override fun onResponse(call: Call<T>, response: Response<T>) {
        if (response.isSuccessful) {
          val body = response.body()
          if (body == null) {
            val invocation = call.request().tag(Invocation::class.java)!!
            val method 
= invocation.method()
            val e = KotlinNullPointerException("Response from " +
                method.declaringClass.name +
                '.' +
                method.name +
                " was null but response body type was declared as non-null")
            continuation.resumeWithException(e)
          } else {
            continuation.resume(body)
          }
        } else {
          continuation.resumeWithException(HttpException(response))
        }
      }

      override fun onFailure(call: Call<T>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
}

也就是说,非协程与协程下的Retrofit的工作流程差不多。协程情况下,在RequestFactory解析,确定是协程,在HttpserviceMethod解析走不同的路径,通过Call扩展函数实现网络请求。

动态代理

说到动态代理,总是离不开静态代理和代理模式。静态代理总是要写接口,然后代理类和被代理类实现该接口,客户端通过代理类使用接口提供的功能,而代理类把功能实际的工作转到被代理类。问题在哪里,每次我们都懂得去实现代理类和代理类,如果很多个接口,这样会很累的,毕竟程序员都是懒的。再说如果这样,用Retrofit这种第三方库,怎么知道用户创建什么样的接口,怎么去实现他们功能?那就是利用Java的动态代理技术了。动态代理在使用上也可以理解是一套模板。

首先,定义接口,以及实现类,也就是我们对外提供的功能。

public interface Service {
    void coding();
}

public class CoderService implements Service {
    @Override
    public void coding() {
        System.out.println("提供编程服务");

    }
}

第二,实现InvocationHandler的子类。核心点在于实现invoke函数,调用接口的函数都会转到这里来。

public class Handler implements InvocationHandler {

    private Object service;

    public Handler(Object service) {
        this.service = service;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("开发了");
        method.invoke(service,objects);
        System.out.println("结束了");
        return null;
    }
}

最后,创建Proxy.newProxyInstance接口对象。在Java中,接口和抽象类是不能被直接实例化的。

public class Main {
    public static void main(String[] args) {
        Service service = new CoderService();
        InvocationHandler handler = new Handler(service);
        Service se = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), new Class[]{Service.class}, handler);
        se.coding();
    }
}

这样就可以通过实例化的接口对象,使用相关功能。

Retrofit通过在InvocationHandlerinvoke解析Method来获得网络请求所需要的的数据。

总结

Retrofit通过Java动态代理技术生成我们请求接口的对象,而我们调用对象的任何函数时,其实都转到InvocationHandler对象的invoke函数。而invoke函数的主要工作就是解析我们在接口中定义函数,包括解析注解,参数注解及值,以及返回类型,然后封装到RequestFactory,然后通过HttpServiceMethod.parseAnnotations函数,查找合适的请求适配器和响应转换器,最后将RequestFactory和适配器、转换器封装成HttpServiceMethod的子类,并调用其invoke函数,通过OkHttp发起网络请求。

通过源码分析,我们知道,一个优秀的的框架都会使用缓存,例如这里方法的解析,OkHttp请求的缓存。同时也知道Retrofit目前已经支持协程,即挂起函数。


转自:掘金 新小梦

https://juejin.cn/post/6941585326675034143

- EOF -

推荐阅读  点击标题可跳转

1、关于Android架构,你是否还在生搬硬套?

2、Flutter 2.0 下混合开发浅析

3、Flutter 不是真正的跨平台框架


看完本文有收获?请分享给更多人

 推荐关注「安卓开发精选」,提升安卓开发技术

点赞和在看就是最大的支持❤️

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存