Retrofit2源码走读

作者: 进击de小黑 | 来源:发表于2017-08-29 14:22 被阅读71次

Retrofit—Jake Wharton大神的网络请求类库,OkHttp的基础上进行二次封装,使用更加的简单和方便。关于用法在这里就不做赘述了,我们直接打开Retrofit的核心方法create(class<T> service )来做分析。

 public <T> T create(final Class<T> service) {
    //检测是否是interface接口,否则直接抛出异常
    Utils.validateServiceInterface(service);
    //接口是否有更新
    if (validateEagerly) {
      //更新方法Map
      eagerlyValidateMethods(service);
    }
    //Java动态代理
    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);
          }
        });
  }

我们看一下eagerlyValidateMethods方法,首先获取当前Android平台,然后遍历当前Interface的所有method方法,再加载

 private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

loadServiceMethod加载缓存ServiceMethod,或者构建新的ServiceMethod并加入缓存serviceMethodCache

//ConcurrentHashMap并发的线程安全的HashMap
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

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

ServiceMethod,封装了Interface的方法Method、注解、url、httpMethod、Headers等的类

   Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      //注解
      this.methodAnnotations = method.getAnnotations();
      //方法的形式参数类型      
      this.parameterTypes = method.getGenericParameterTypes();
      //方法参数上的注解集合
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

构造ServiceMethod对象

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();
      //解析注解,进行一系列的判断注解的合法性
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
  
      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

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

绕了一圈,我们还是回到Retrofit.create(class<T> service )来。我们看到方法直接return Proxy.newProxyInstance();在这里使用了JavaSE中的动态代理类Proxy,利用反射对方法在new InvocationHandler()的invoke(Object proxy, Method method, Object[] args)方法中进行增强及执行,其中proxy,代理对象;method,代理方法;args,代理参数。

 //如果是Object的方法,直接执行
 if (method.getDeclaringClass() == Object.class) {
     return method.invoke(this, args);
 }
//非安卓平台为true
if (platform.isDefaultMethod(method)) {
      return platform.invokeDefaultMethod(method, service, proxy, args);
 }

如前面的loadServiceMethod一样获取得到ServiceMethod,然后构建OkHttpCall请求并执行获得Call的数据返回。

 ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
 return serviceMethod.callAdapter.adapt(okHttpCall);

这样一个Java接口就被翻译成了OkHttpCall的可执行请求。在OkHttpCall里转换了请求,并使用Okhttp3来进行执行请求,回调Callback。

相关文章

网友评论

    本文标题:Retrofit2源码走读

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