Retrofit源码分析之二

1、从Retrofit源码分析之一,可知retrofit创建时使用代理,接下来分析一下代码:

 public <T> T create(final Class<T> service) {
    //校验是否为接口,且不能继承其他接口
    Utils.validateServiceInterface(service);
    // 是否需要提前解析接口方法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //动态代理,返回一个 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 {
            // 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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

重点看一下代理里中的invoke方法,里面return一个loadServiceMethod.invoke

在代理中,会根据参数中传入的具体接口方法来构造出对应的 serviceMethod 。ServiceMethod 类的作用就是把接口的方法适配为对应的 HTTP 请求

ServiceMethod<?> loadServiceMethod(Method method) {
    //先从缓存中取,若没有就去创建对应的 ServiceMethod
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    //做了同步操作,多线程访问
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      // 没有缓存就创建,之后再放入缓存中
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

可以看出内部还维护了一个 serviceMethodCache 来缓存 ServiceMethod ,同一个 API 的同一个方法,只会创建一次

接下来看parseannotation方法:

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    //将接口传入请求工厂RequestFactory,解析注解
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    //判断返回类型,返回类型不能包含类型变量或通配符,不能为void
    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.");
    }
    //将接口方法的调用调整为HTTP调用
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

2、RequestFactory,作用是将接口注解解析,供http调用

final class RequestFactory {
  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() {
   //遍历接口方法注解,并解析
  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);
      }
  ****省略代码
}

如果是kotlin代码是通过isKotlinSuspendFunction来判断,Continuation在Kotlin里有一个对应interface

if (Utils.getRawType(parameterType) == Continuation.class) {
  isKotlinSuspendFunction = true;
  return null;
}

3、HttpServiceMethod,将接口方法的调用调整为HTTP调用,并适配不同平台

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;
  //判断是否为kotlin接口
  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();
  if (responseType == okhttp3.Response.class) {
    throw methodError(method, "'"
        + getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  if (responseType == Response.class) {
    throw methodError(method, "Response must include generic type (e.g., Response<String>)");
  }
  // TODO support Unit for Kotlin?
  if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
    throw methodError(method, "HEAD method must use Void as response type.");
  }
 
  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);
  //将默认的网络请求执行器(OkHttpCall)转换成适合被不同平台来调用的网络请求执行器形式
  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  if (!isKotlinSuspendFunction) {
    return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
  } else if (continuationWantsResponse) {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
        callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
  } else {
    //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
    return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
        callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
        continuationBodyNullable);
  }
}

Retrofit源码分析之一

Retrofit源码分析之三

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值