Bootstrap

Retrofit使用及解析(三)

目录

1.Retrofit.create(接口类) 

1)提前验证

2)动态代理部分

核心1-ServiceMethod:

a.讲解一:CallAdapter()

b.讲解二:createResponseConverter()

c:总结ServiceMethod的build()

核心2-OkHttpCall :

核心3-CallAdapter.adapt()

2.拿到动态代理对象,预备执行网络请求

3.OKhttpCall执行请求

1)execute

2)enqueue()


1.Retrofit.create(接口类) 

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, 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 serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

1)提前验证

Retrofit的成员变量validateEagerly,为true表示提前验证,看看eagerlyValidateMethods():

  private void eagerlyValidateMethods(Class<?> service) {
    //获取平台  android? ios?
    Platform platform = Platform.get();
    //遍历service接口类方法
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
        loadServiceMethod(method);
      }
    }
  }

看看isDefaultMethod(..):

//默认返回false
boolean isDefaultMethod(Method method) {
    return false;
}

当非默认方法,调用loadServiceMethod(..):

public final class Retrofit {

  private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();

  ServiceMethod loadServiceMethod(Method method) {
    //ServiceMethod即对接口单个方法的封装
    ServiceMethod result;
    //锁缓存ServiceMethod的map
    synchronized (serviceMethodCache) {    
       //先从缓存拿
      result = serviceMethodCache.get(method);
      if (result == null) {   
        //构建模式 创建ServiceMethod  -> 放入缓存
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    //最终返回ServiceMethod 
    return result;
  }

    ...
}

2)动态代理部分

接下来再回去看看create()后面的操作:

public <T> T create(final Class<T> 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, Object... args)throws Throwable {
            //非android平台:方法是Object中的方法(equals等等)
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //非android平台
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //核心1:android平台
            //ServiceMethod对应retrofit接口类中的一个方法
            //loadServiceMethod方法介绍过,判断缓存是否有对应的ServiceMethod 
            ServiceMethod serviceMethod = loadServiceMethod(method);
            //核心2
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //核心3
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

核心1-ServiceMethod:

final class ServiceMethod<T> {
  ...

  final okhttp3.Call.Factory callFactory; //网络请求工厂,生产网络请求
  final CallAdapter<?> callAdapter;//网络请求适配器,将call请求适用各平台
  private final HttpUrl baseUrl;//基础url
  private final Converter<ResponseBody, T> responseConverter;//数据转化器
  private final String httpMethod;//请求方法 get post
  private final String relativeUrl;//网络请求的相对地址,和基础url拼接成完成地址
  private final Headers headers;//请求头
  private final MediaType contentType;//请求http报文的body类型
  //标志位
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  //用途:解析retrofit接口类的方法和方法上注解  
  private final ParameterHandler<?>[] parameterHandlers;

  //构建者模式 实现 初始化
  ServiceMethod(Builder<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;
  }

    ...

    static final class Builder<T> {
    
        ...
        public Builder(Retrofit retrofit, Method method) {
            this.retrofit = retrofit;
            //请求方法
            this.method = method;
            //接口方法中的注解  比如@path @get等
            this.methodAnnotations = method.getAnnotations();
            //获取接口方法里面参数的类型
            this.parameterTypes = method.getGenericParameterTypes();
            //获取接口方法里面参数的内容
            this.parameterAnnotationsArray = method.getParameterAnnotations();
        }

         public ServiceMethod build() {
    //下方讲解(讲解一)  作用: 根据网络请求接口方法的返回值和注解类型,从retrofit获取对应的
    //网络接口适配器
             callAdapter = createCallAdapter();
    //下方讲解  作用:从callAdapter(根据网络请求接口方法的返回值和注解类型)获取网络适配器
    //返回的数据类型
             responseType = callAdapter.responseType();

      ...
      //创建数据转换器  下方讲解(讲解二) 
      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];
         //遍历通过parseParameter解析参数
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
        ...
      return new ServiceMethod<>(this);
    }
    }
}

a.讲解一:CallAdapter()

    private CallAdapter<?> createCallAdapter() {
      //获取接口方法的返回类型
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
       ...

      //获取接口方法里面的注解类型
      Annotation[] annotations = method.getAnnotations();
      try {
            //从retrofit获取对应的网络请求适配器
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { 
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }

看看retrofit.callAdapter(returnType, annotations):

  public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
 public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    ...

    
    int start = adapterFactories.indexOf(skipPast) + 1;
    //遍历CallAdapter工厂集合,寻找合适的工厂
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
       //合适时候,通过get()创建需要的CallAdapter
       CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
       //无合适的抛出异常
       if (adapter != null) {
            return adapter;
       }
    }

       ...
  }

b.讲解二:createResponseConverter()

    private Converter<ResponseBody, T> createResponseConverter() {
      //获取方法的注解类型
      Annotation[] annotations = method.getAnnotations();
      try {
        //返回Converter
        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);
      }
    }

进入responseBodyConverter():

  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
      Type type, Annotation[] annotations) {
   ...
    //找到合适的数据解析器 默认json,即jsonResponseBodyConverter
    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;
      }
    }
        ...
  }

c:总结ServiceMethod的build()

封装了请求头,请求方式,请求路径等等,并创建好网络请求适配器、数据转换器,最终通过parameterHandlers遍历解析retrofit接口类的方法和方法上注解。

 

核心2-OkHttpCall :

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
final class OkHttpCall<T> implements Call<T> {

  //请求参数等等信息
  private final ServiceMethod<T> serviceMethod;
  //接口参数
  private final Object[] args;
  //是否取消请求
  private volatile boolean canceled;
  //调用的原生OKhttp的call
  private okhttp3.Call rawCall;
  //异常
  private Throwable creationFailure; 
  //请求已执行的标志
  private boolean executed;

  OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }

    ...
}

核心3-CallAdapter.adapt()

return serviceMethod.callAdapter.adapt(okHttpCall);

serviceMethod.callAdapter的创建是在serviceMethod的build()方法中去创建的。而adapt方法前面也提过,就是把Retrofit中的每一个call转换成其他平台也可以使用的类型(比如rxjava中就被转换成rxjava所使用的类型)。

2.拿到动态代理对象,预备执行网络请求

通过第1点的Retrofit.create(接口类),我们知道返回的是动态代理的接口类,即

Api api=retrofit.create(Api.class);

此时当我们调用接口中的方法,比如:

Call call=api.getCall();

此时的call就是动态代理后返回给我们的OKhttpCall,且OKhttpCall是对okhttp网络库的封装,这样就串联了起来,后面再看看真正的请求的同步和异步执行。

3.OKhttpCall执行请求

分为:同步execute和异步enqueue请求

1)execute

public Response<T> execute() throws IOException {

    //底层的okhttp的call
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");

      //已执行的标志
      executed = true;

      ...

      call = rawCall;
      if (call == null) {
        try {
          //下方讲解
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }
    
    //通过标志位取消请求
    if (canceled) {
      call.cancel();
    }

    //okhttp库请求得到数据,并在解析后被返回  
    return parseResponse(call.execute());
  }

 看看call的创建->createRawCall()

  private okhttp3.Call createRawCall() throws IOException {
    //生成request 如何生成,待会看看
    Request request = serviceMethod.toRequest(args);
    //生成okhttp3.Call
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

看Request如何生成:

  Request toRequest(Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

   ...
    //ParameterHandler解析
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    ...

    return requestBuilder.build();
  }

在看看serviceMethod.callFactory.newCall(request),发现最终调用的是:

  protected RealCall(OkHttpClient client, Request originalRequest) {
    this.client = client;
    this.originalRequest = originalRequest;
  }

而RealCall是okhttp库中的call的实现类,代表此时的网络请求已交给okhttp处理。

在看看execute最后返回的数据,parseResponse(call.execute()):

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    ...
    //响应码判断
    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      ...
    }

    if (code == 204 || code == 205) {
      ...
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      //处理响应体
      T body = serviceMethod.toResponse(catchingBody);
      //处理后的数据,返回给retrofit的成功响应回调
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      catchingBody.throwIfCaught();
      throw e;
    }
  }

进入serviceMethod.toResponse(catchingBody):

  T toResponse(ResponseBody body) throws IOException {
    //调用数据转换器转换响应数据
    return responseConverter.convert(body);
  }

流程总结:由ParameterHandler对接口方法和方法参数进行解析   ->  将请求所需信息封装到ServiceMethod  ->  根据ServiceMethod 创建okhttp的request  ->  用okhttpcall(底层okhttp)执行请求  ->  converter解析最终返回数据

2)enqueue()

public void enqueue(final Callback<T> callback) {
    ...

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      ...
      //已执行标志位
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          //内部创建request和call,返回call
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

   ...
    //取消请求
    if (canceled) {
      call.cancel();
    }

    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
            //将解析后的响应数据赋值response
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        //回调返回数据
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
            //失败回调
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
             //失败回调
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
            //成功回调
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

 

 

 

;