Retrofit(三)

Android知识总结

一、ServiceMethod

ServiceMethod是一个负责转化(适配)的类,负责把一个接口的抽象方法的执行过程的结果转化(适配)成一个网络请求(HTTP call)。

1、ServiceMethod 内部参数

final class ServiceMethod {
  // 用来校验的常量
  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
  /**
   * 网络请求工厂,用于生产我们的网络请求,
   * 这个call在Retrofit当中其实就是我们的OKHTTP Call,
   * 而OKHTTP Call呢就是Retrofit对它做了封装。它内部其实是调用了OKHTTP Call。
   */
  private final okhttp3.Call.Factory callFactory;
  // 网络请求适配器,把我们的Call请求适用于不同的平台。例如:RxJava等。
  private final CallAdapter callAdapter;
  //基础HttpUrl
  private final HttpUrl baseUrl;
  // 数据转换器。作用就是把服务器返回给我们的数据,转换成我们需要的java Bean对象。
  private final Converter responseConverter;
  // 网络请求的HTTP方法,比如:get, post, put等等。
  private final String httpMethod;
  // 网络请求的相对地址。 相对地址 + 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;
  ...
}

2、ServiceMethod.Builder构造方法

 //Retrofit
    final Retrofit retrofit;
    //定义接口的抽象方法
    final Method method;
    //定义接口的抽象方法上面的注解数组
    final Annotation[] methodAnnotations;
     //注解二维数组:第一维对应参数序列,第二维对应注解序列;
    final Annotation[][] parameterAnnotationsArray;
     // 参数类型数组
    final Type[] parameterTypes;
    // 响应的类型
    Type responseType;
    //是否有用 @Field 或者FieldMap 注解
    boolean gotField;
     //是否 有用@Part 或者 @PartMap注解
    boolean gotPart;
    //是否有用 @body注解
    boolean gotBody;
     // 是否 有用@Path 注解
    boolean gotPath;
     //是否 有用@Query 或者@QueryName 注解
    boolean gotQuery;
     // 是否具有url
    boolean gotUrl;
     //http 请求的方法
    String httpMethod;
     //是否  需要请求体
    boolean hasBody;
    //是否 使用@FormUrlEncoded  注解
    boolean isFormEncoded;
    // 是否 使用了@Multipart  注解
    boolean isMultipart;
    // 相对路径
    String relativeUrl;
     //请求头
    Headers headers;
    //类型
    MediaType contentType;
     //相对路径的url参数
    Set relativeUrlParamNames;
     //参数处理数组
    ParameterHandler[] parameterHandlers;
     //响应转化器
    Converter responseConverter;
     //请求转化器
    CallAdapter callAdapter;

    Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      // 获取网络请求方法(get,post等)
      this.method = method;
      // 获取网络请求接口方法里面的注解
      this.methodAnnotations = method.getAnnotations();
      // 获取网络请求接口方法里的参数的类型,它是一个types。
      this.parameterTypes = method.getGenericParameterTypes();
      // 获取网络请求接口方法里注解的完整内容
      this.parameterAnnotationsArray = method.getParameterAnnotations()
    }
  • build()方法
    public ServiceMethod build() {
      // 查找能够适配返回类型的CallAdpater
      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?");
      }
      //设置请求的数据适配器 converter
      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);
      }

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

ServiceMethod#createCallAdapter

    private CallAdapter 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.");
      }
      //获取网络请求接口里的注解,调用的反射当中的getAnnotations()。
      Annotation[] annotations = method.getAnnotations();
      try {
        //noinspection unchecked  callAdapter(返回值, 注解类型)
        return (CallAdapter) 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);
      }
    }

获取方法的返回类型默认调用ExecutorCallAdapterFactory#CallAdapter#responseType 方法:

  @Override
  public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //method方法返回值类型必须是Call
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    //获取Call的泛型T的类型
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter>() {
      @Override public Type responseType() {
        //Call那么返回的就是JavaBean
        return responseType;
      }
      //最终invoke会执行的方法
      //adapt方法参数的call就是OKhttpCall
      @Override public Call adapt(Call call) {
        //callbackExecutor是MainThreadExecutor 
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

调用ServiceMethod#createResponseConverter方法设置请求的数据适配器:

    private Converter createResponseConverter(){
      Annotation[] annotations = method.getAnnotations();
      try {
        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);
      }
    }

调用ServiceMethod#parseMethodAnnotation方法解读方法的注解:

    private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
        if (!Void.class.equals(responseType)) {
          throw methodError("HEAD method must use Void as response type.");
        }
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError("@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

二、 OkHttpCall

OkHttpCall仅仅是一个包装类,外部使用Retrofit.Call,其实内部调用的是Okhttp3.Call,由OkHttpCall来实现调度。所以对外部来说,无需关心 网络层 倒是怎么操作的。在内部进行网络请求

1、 分析成员变量

  //方法处理类,后面详解讲解,大家这里有个印象即可
  private final ServiceMethod serviceMethod;
  //和方法处理类一样,其实是调用方法的入参,大家先知道就可以,后期会详细讲解。
  private final Object[] args;
  // 判断 是否已经取消了。
  //volatile,如果有同学不清楚,请直接百度下,这个关键字还是很重要的,主要用于多线程使用的背景下。
  private volatile boolean canceled;
  // All guarded by this.
  //真正的okhttp3.Call,真正的请求
  private okhttp3.Call rawCall;
  // 异常,包括IO和运行时异常
  private Throwable creationFailure; // Either a RuntimeException or IOException.
  //是否已经启动
  private boolean executed;

2、执行异步请求

  @Override public void enqueue(final Callback callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true; // 标识该执行器正在执行

      call = rawCall;  // 得到OkHttp.call 
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall(); //如果为空就创建OkHttp.call
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {  // OkHttp.call 构造失败
      callback.onFailure(this, failure);
      return;
    }
    // 用户取消了执行器的执行
    if (canceled) { 
      //去执行OkHttp.call 的取消行为
      call.cancel();
    }
    //OkHttp.call 真正的执行过程
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response response;
        try {
          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 response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

3、执行同步请求

  @Override public Response execute() throws IOException {
    okhttp3.Call call;

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

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else {
          throw (RuntimeException) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall(); //如果为空就创建OkHttp.call
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    //执行请求
    return parseResponse(call.execute());
  }

4、创建 okhttp3.Call

  private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

三、RequestBuilder类

通过字面大家就能猜到了他是一个Request的builder类。这个Request是okhttp3.Request。
RequestBuilder这个类,主要就是用于创建一个okHttp的Request,里面有很多方法用于设置Request的一些参数。

1、变量分析

  //请求类型,post或者get
  private final String method;
   //Http的url  根地址
  private final HttpUrl baseUrl;
   //相对路径的url,对应的是具体的接口
  private String relativeUrl;
   //HttpUrl的Builder
  private HttpUrl.Builder urlBuilder;
  //okHttp3里面的Request.Builder
  private final Request.Builder requestBuilder;
  // MediaType 也是okHttp3里面的MediaTyep。MediaType即是Internet Media Type,互联网
  //媒体类型;也叫做MIME类型,在http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。
  private MediaType contentType;
  // 布尔类型,代表都是有body
  private final boolean hasBody;
   //okHttp3里面的MultipartBody的builder
  private MultipartBody.Builder multipartBuilder;
  //okHttp3里面的FormBody的builder
  private FormBody.Builder formBuilder;
  //okHttp3里面的RequestBody
  private RequestBody body;

2、相关的set方法分析

  • setRelativeUrl:设置相对路径的url
  • addHeader:添加请求头
  • addPathParam:添加PathParam参数
  • addQueryParam:添加请求参数,如果是GET方法,直接拼接在相对路径上,如果是post方式则直接放到消息体,这里面其实通过okHttp3的HttpUrl.Builder来实现的。
  • addFormField:添加表单,key-value键值对的形式
  • addPart:这个方法有两个重载,一个是根据header和body来添加MultipartBody,另外一个是直接添加MultipartBody
  • setBody:设置请求的bod

四、总结

一般的Retrofit网络请求的操作是指 Call.excute() & Call.enqueue()的过程,这个过程才是真正的网络请求,因为,网络配置,请求地址配置,Call适配,网络请求 requestBody &返回值responseBody转化适配准备工作都已经完成。

sharedListCall.enqueue(new Callback()...);
sharedListCall.excute();

在进行网络请求的执行的时候,基本上就是调用,ServiceMethod中设置的各个内容如 :

  • 1)OkHttpCall进行网络请求,实则是进行okhttp的网络请求;
  • 2)利用 converter进行网络请求数据的转换,一般是Gson();
  • 3)利用 rxjava observable构建 rxjava类型的责任链访问方案,并进行线程切换;
    1. 如果没有rxjava的添加,那么就使用默认的callAdapter里面的callbackExecutor进行线程的切换, 进行网络请求.

整体网络请求的流程图请看下图:


请求过程图

你可能感兴趣的:(Retrofit(三))