美文网首页网络
retrofit源码分析(二)

retrofit源码分析(二)

作者: 晓晓桑 | 来源:发表于2019-08-18 22:31 被阅读0次

创建网络接口实例

retrofit把网络请求地址分成两个部分,一个baseurl,一个创建网络接口的地址。注意的是,如果创建网络接口的地址可以生成完成的地址的话,可以不设置baseurl地址。

retrofit.create

 public <T> T create(final Class<T> service) {
//接口传进来的地址进行验证
    Utils.validateServiceInterface(service);
//validateEagerly :成员变量的标志位,作用:是否提前解析这个接口
    if (validateEagerly) {
//<-------eagerlyValidateMethods看下面----------->
      eagerlyValidateMethods(service);
    }
//动态代理模式,当被代理类service调用接口实现的方法时,就会触发第三个参数的InvocationHandler类里面的invoke方法,在invoke方法里做一系列的解析接口的操作
    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.
// 因为是安卓平台。下面两个判断都是false,不会走
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
//直接看下面三行
**//下面三行,是retrofit最经典最核心的三行代码**
//<-------loadServiceMethod 下面有----->
//loadServiceMethod作用:创建获取出去我们接口中定义好的网络请求方法比如我自己写的RetrofitService类中的getCode()
            ServiceMethod<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);
<-----------OkHttpCall类在下面有-------->
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//这个其实是serviceMethod类中通过createCallAdapter()创建类CallAdapter类型对象,CallAdapter调用adapt()
//adapt把retrofit的call转化为各个平台的call
            return serviceMethod.adapt(okHttpCall);
          }
        });
  }

<---------eagerlyValidateMethods----->
//service
  private void eagerlyValidateMethods(Class<?> service) {
//获取平台,android、ios、java8
    Platform platform = Platform.get();
//service.getDeclaredMethods():service类的所有方法
    for (Method method : service.getDeclaredMethods()) {
//默认!platform.isDefaultMethod(method)=true
      if (!platform.isDefaultMethod(method)) {
<---------loadServiceMethod看下面----->
        loadServiceMethod(method);
      }
    }
  }

<---------loadServiceMethod----->
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
//ServiceMethod :对应一个我们自己写的网络请求的service接口的方法
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
    //serviceMethodCache缓存中找ServiceMethod
      result = serviceMethodCache.get(method);
// 如果找不到,创建并且保存到缓存。再回去看creat()
      if (result == null) {
//看一下ServiceMethod类
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

ServiceMethod类

final class ServiceMethod<R, T> {
//网络请求的工厂,用于生产网络请求的call
  private final okhttp3.Call.Factory callFactory;
//网络请求适配器,把call请求适用于不同的平台
  private final CallAdapter<R, T> callAdapter;

//网络基地址
  private final HttpUrl baseUrl;
//response转化器,把接口数据转化成需要的java bean对象
  private final Converter<ResponseBody, R> responseConverter;

//网络请求的方法,比如:get post pull delate等
  private final String httpMethod;
//相对url:就是出去baseurl剩下的部分
  private final String relativeUrl;
//http的请求头,是键值对
  private final Headers headers;
//http网络请求报文的body类型
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
//网络请求接口的方法、注解等的处理器
  private final ParameterHandler<?>[] parameterHandlers;

//构造函数。利用构造者模式
  ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;

···
  }

ServiceMethod.Builder类

  static final class Builder<T, R> {
    ···
    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
     //网络请求接口的方法
      this.method = method;
     //网络请求接口的方法的注解:比如@GET、@POST等待
      this.methodAnnotations = method.getAnnotations();
   //网络请求接口的方法的参数的类型
      this.parameterTypes = method.getGenericParameterTypes();
   //网络请求接口的方法里面参数注解里的完整的内容
      this.parameterAnnotationsArray =method.getParameterAnnotations();
    }

public ServiceMethod build() {
     //createCallAdapter()根据接口方法的返回值和注解类型,从retrofit中获取对应的网络请求适配器
<----------createCallAdapter()在下面-------->
      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();

//遍历methodAnnotations注解数组,对接口中的方法进行解析
      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);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }
}

createCallAdapter()

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

createResponseConverter()

    private Converter<ResponseBody, T> createResponseConverter() {
//获取网络请求方法的注解
      Annotation[] annotations = method.getAnnotations();
      try {
//返回一个converter,
<---------responseBodyConverter()见下面--------->
        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;
      }
    }

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

ServiceMethod.build()总结:根据我们的返回值类型,和方法中的注解,从网络请求适配器工厂和数据转化器工厂集合中分别获取到我们所需要的网络请求适配器和数据转化器,然后根据我们参数的注解获取到我们所需要的解析的参数,最后调用parseParameter(p, parameterType, parameterAnnotations)解析我们接口中的参数

OkHttpCall

final class OkHttpCall<T> implements Call<T> {
//ServiceMethod:网络请求信息的对象(参数啊 url等)
  private final ServiceMethod<T, ?> serviceMethod;
//网络请求接口的参数
  private final @Nullable Object[] args;
//标志位,是否取消网络请求
  private volatile boolean canceled;
//okhttp原生的call,实际进行网络访问
  private @Nullable okhttp3.Call rawCall; 
// 标志位:请求异步方法
  private boolean executed;
  private @Nullable Throwable creationFailure;

//构造方法
//传入的是serviceMethod对象(此对象是方法,注解、参数类型、参数注解的信息)
//args:是参数数组
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
}

Retrofit实现

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Api.APP_DOMAIN)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        retrofitService = RetrofitService retrofit.create(RetrofitService.class);
  Call<BaseResponseBean> call = retrofitService.getCode(type, phone);
        call.enqueue(new Callback<BaseResponseBean>() {
            @Override
            public void onResponse(Call<BaseResponseBean> call, Response<BaseResponseBean> response) {
                response.code();
            }

            @Override
            public void onFailure(Call<BaseResponseBean> call, Throwable t) {
                t.toString();
            }
        });

问题:retrofitService.getCode(type, phone);接口怎么能请求方法呢?
答:因为retrofit.create里使用类动态代理,调用了Proxy.newProxyInstance()进行拦截,调用了InvocationHandler里面的invoke()方法进行实际的操作,最后会返回给OkHttpCall类型的call对象来实际进行网络请求,OkHttpCall是对okhttp的网络封装。

相关文章

网友评论

    本文标题:retrofit源码分析(二)

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