Retrofit 源码简介

我们先洗个请求的例子,如下

    private void retrofitTest() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://wwwcom/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();
        ApiService service = retrofit.create(ApiService.class);

        Call<String> call = service.getBlog("https://www.baidu.com", "abc");
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
           
            }

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


    interface ApiService {
        @GET
        Call<String> getBlog(
                @Url String url,
                @Query("type") int type
        );

        @FormUrlEncoded
        @POST()
        Call<String> getBlog1(
                @Url String url,
                @Field("type") String type,
                @Field("address") String address
        );

    }

例子是个get请求,ApiService 类中,使用了 @GET 注解,形参中使用了 @Url 和 @Query 注解,一旦使用 @Url,则以它对应的值为准,Retrofit.Builder()  中通过 baseUrl() 设置的基准url就不使用了;如果我们使用post请求,用表格形式,接口中方法除了使用 @POST() 注解外,还要使用 @FormUrlEncoded 注解,对应的形参中要有 @Field 或 @FieldMap 其中之一,否则会报错。


Retrofit 是载体,我们看看它的代码,首先是个 Builder 模式,构造方法中有个参数

    public Builder() {
      this(Platform.get());
      converterFactories.add(new BuiltInConverters());
    }

看看 Platform.get() 对应的值

  private static final Platform PLATFORM = findPlatform();
  static Platform get() {
    return PLATFORM;
  }

private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    ...
    return new Platform();
  }

我们是在 Android 设备上使用该网络库,此时对应的就是 new Android() 生成的对象,看看它是什么 

  static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

它里面有两个方法,返回的对象分别是 MainThreadExecutor 和 ExecutorCallAdapterFactory。MainThreadExecutor 实现了 Executor 接口,方法中通过一个对应UI线程的Handler,把runnable 切换到主线程中。 retrofitTest() 中,如果在 Retrofit.Builder() 时,直接调用了 build() 方法

  public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
  }

第一步就抛异常,所以 baseUrl 必须设置,按照规范,以反斜线结尾;如果没设置 callFactory,则在这里new一个OkHttpClient对象,它是 Okhttp 中的类,我们如果要定制,就在外部创建好,然后通过 callFactory() 方法设置进来;callbackExecutor 也是同样道理,默认使用就是 MainThreadExecutor 这个类;adapterFactories 是个空集合,这里往里面添加了一个对象,就是 ExecutorCallAdapterFactory,它的构造方法中接收了 MainThreadExecutor 这个类;

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public <R> Call<R> adapt(Call<R> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
}


注意它内部 get() 方法返回的对象是 CallAdapter 类型,在这里是 new 出的一个对象,它里面又有两个方法,其中创建 ExecutorCallbackCall 对象时把 callbackExecutor 和 call传递了进去。

converterFactories 集合在 Builder 的构造方法中传递了一个 BuiltInConverters 对象,它是 Converter.Factory 的子类,里面有三个方法,根据名字可知,responseBodyConverter() 是把返回的 ResponseBody 对象转换为定义的对象 requestBodyConverter() 是把请求的对象转换为 RequestBody,stringConverter() 是把请求参数转换为 String 类型,以上三个方法不一定都会用到。我们也可以继承 Converter.Factory ,根据自己的业务逻辑,来自定义自己的类。最后用这些参数创建一个 Retrofit 对象。


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


这是个动态代理,动态代理的底层原理还是反射;这一步仅仅是通过传入一个class文件,返回一个对应的对象,动态代理的 InvocationHandler 中的方法并没有执行,service.getBlog("https://www.baidu.com", "abc") 执行这行代码时,才会触发 InvocationHandler 中的 invoke(Object proxy, Method method, Object... args) 方法,此时 proxy 代表的是 retrofit 对象,method 代表的是对应方法 getBlog(),args这个可变参数对应的是 method 方法中的参数,在这里对应的是 "https://www.baidu.com" 和 "abc" 这两个参数。动态代理的常规用法是传入一个代理对象,通过 Proxy 创建对象并返回,然后再外部调用方法,触发invoke() 方法中通过拿到的参数进行反射来触发要调用的方法。 Retrofit 中的这个动态代理没按照常规的逻辑执行,来看看它都做了什么,先看 loadServiceMethod(method) 方法


  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }


这个里面是个Map缓存,如果有,则复用;如果没有,则创建,这里又引申出一个比较重要的类 ServiceMethod,它也是采用了 Builder 模式,看看其方法

    public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

上一篇文章中讲过方法中 Method 中这几个方法的作用,这里不再重复,看看 build() 方法

  public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      responseConverter = createResponseConverter();
      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }
      ...
      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
       ...
      return new ServiceMethod<>(this);
  }

此方法省略了一些校验的代码,有兴趣的可以看一下源码,这里讲一下大框架流程。createCallAdapter() 方法中获取的是其实就是上面的 ExecutorCallAdapterFactory 中创建的对象

  private CallAdapter<?> createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      Annotation[] annotations = method.getAnnotations();
      try {
        return 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);
      }
  }

Retrofit:

  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;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
    ...
    throw new IllegalArgumentException(builder.toString());
  }

returnType 是方法返回值的类型,adapterFactories 就是Retrofit中创建时添加对象的集合,此时遍历集合,通过 get() 方法来判断是否是需要的 CallAdapter,ExecutorCallAdapterFactory 中的 get() 方法返回的对象是 new 出来的 CallAdapter 对象,不为空,所以就是它了。

createResponseConverter() 方法返回对象 responseConverter,它的作用是响应体转换器,看看它的代码

  private Converter<ResponseBody, T> 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);
      }
  }


Retrofit:

  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) {
    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) {
        return (Converter<ResponseBody, T>) converter;
      }
    }
    ...
    throw new IllegalArgumentException(builder.toString());
  }

这个与上面的原理类似,由于该集合中有 BuiltInConverters 和 ScalarsConverterFactory 两个对象,一个是系统自带的,一个是我们方法中设置进去的,这时候会遍历,根据 responseBodyConverter() 返回值来确定使用哪个,BuiltInConverters 中的 Type 类型只支持两种,即 ResponseBody 和 Void,而我们这个接口中使用的返回值类型是 String,所以这个里面没有合适的,继续看 ScalarsConverterFactory,它里面支持 String 类型,返回的是 ScalarRequestBodyConverter 对象。

final class ScalarRequestBodyConverter<T> implements Converter<T, RequestBody> {
  static final ScalarRequestBodyConverter<Object> INSTANCE = new ScalarRequestBodyConverter<>();
  private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain; charset=UTF-8");

  private ScalarRequestBodyConverter() {
  }

  @Override public RequestBody convert(T value) throws IOException {
    return RequestBody.create(MEDIA_TYPE, String.valueOf(value));
  }
}

接着是遍历 methodAnnotations 这个方法上的注解数组,我们例子中只有一个 @GET 注解,看看 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) {
        ...
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
  }

  private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
      this.httpMethod = httpMethod;
      this.hasBody = hasBody;

      if (value.isEmpty()) {
        return;
      }
    ...
  }

这个方法就是确认请求头中请求格式,并做一些属性赋值,做逻辑判断。继续往下看,parameterAnnotationsArray 对应的形参中的注解,ParameterHandler 是个接口,这里是为了适配各种类型,注意 parseParameter() 方法

  private ParameterHandler<?> parseParameter(int p, Type parameterType, Annotation[] annotations) {
      ParameterHandler<?> result = null;
      for (Annotation annotation : annotations) {
        ParameterHandler<?> annotationAction = parseParameterAnnotation(p, parameterType, annotations, annotation);
        if (annotationAction == null) {
          continue;
        }
        if (result != null) {
          throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
        }
        result = annotationAction;
      }
      if (result == null) {
        throw parameterError(p, "No Retrofit annotation found.");
      }
      return result;
  }


这段代码的意思是,Call<String> getBlog(@Url String url,@Query("type") int type) 这个方法中,以它为例子,parameterAnnotationsArray 数组长度为2,第一个数组中对应的是 @Url String url 这个形参中的 @Url 注解,此时,p为0,parameterType 为String,annotations 数组中只有一个对象,指的是@Url,再通过 parseParameterAnnotation() 方法来生成
ParameterHandler 对象

  private ParameterHandler<?> parseParameterAnnotation(
        int p, Type type, Annotation[] annotations, Annotation annotation) {
      if (annotation instanceof Url) {
        ...
        gotUrl = true;
        if (type == HttpUrl.class || type == String.class || type == URI.class
            || (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
          return new ParameterHandler.RelativeUrl();
        } else {
          throw parameterError(p,
              "@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
        }

      } else if (annotation instanceof Query) {
        Query query = (Query) annotation;
        String name = query.value();
        boolean encoded = query.encoded();

        Class<?> rawParameterType = Utils.getRawType(type);
        gotQuery = true;
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          ...
        } else {
          Converter<?, String> converter = retrofit.stringConverter(type, annotations);
          return new ParameterHandler.Query<>(name, converter, encoded);
        }
      } else if (annotation instanceof Field) {
        if (!isFormEncoded) {
          throw parameterError(p, "@Field parameters can only be used with form encoding.");
        }
        Field field = (Field) annotation;
        String name = field.value();
        boolean encoded = field.encoded();
        gotField = true;

        Class<?> rawParameterType = Utils.getRawType(type);
        if (Iterable.class.isAssignableFrom(rawParameterType)) {
          ...
        } else {
          Converter<?, String> converter = retrofit.stringConverter(type, annotations);
          return new ParameterHandler.Field<>(name, converter, encoded);
        }
      }
      ...
      return null; // Not a Retrofit annotation.
  }

这是简化后的代码,以 @GET、@Query、@Field 为例,方法形参 type 代表的是参数类型,annotations 是注解数组,只有一个对象,annotation 就是我们具体的注解,即 GET、Query、Field 等等,我们先看 Url,一堆校验后走到了 if 判断,此时我们参数是String类型,所以retrun的对象是 RelativeUrl,它是 ParameterHandler 的子类;Query 中,根据注解获取对应的值,query.value() 对应的就是type字符串,query.encoded() 默认是false,调用 retrofit.stringConverter(type, annotations) 获取对象,此时会重新遍历 converterFactories 集合,通过调用 stringConverter() 方法获取对应的值,这一次 BuiltInConverters 对象符合条件,返回的是 StringConverter 

  static final class StringConverter implements Converter<String, String> {
    static final StringConverter INSTANCE = new StringConverter();

    @Override public String convert(String value) throws IOException {
      return value;
    }
  }


获取 Converter 后,创建 ParameterHandler.Query 对象;Field 注解中,会先校验 isFormEncoded 属性,这也是为什么必须使用 @FormUrlEncoded 注解的原因,最后返回 ParameterHandler.Field 对象,与 Query 类似。parameterHandlers 数组填充完毕后,会再校验一些属性,这个也可以称之为注解的组合使用规则。然后就是通过builder方法创建 ServiceMethod 对象了,把 Builder 中获取的值,尽数传递给 ServiceMethod。

loadServiceMethod(Method method) 方法分析到此结束,继续看动态代理的内容,创建 OkHttpCall 对象,把 serviceMethod 和参数 args 通过构造方法传递进去,然后调用 ServiceMethod 中的 callAdapter 属性对象的 adapt() 方法,此时 callAdapter 对应的就是 createCallAdapter() 方法生成的 ExecutorCallAdapterFactory 类中的 get() 方法中 return 的 CallAdapter 对象;serviceMethod.callAdapter.adapt(okHttpCall)  对应的就是 CallAdapter 对象中的 adapt()  方法,它 return 的值是 ExecutorCallbackCall, Call<String> call =  service.getBlog( "https://www.baidu.com" ,  "abc" ) 中 call 实际上就是 ExecutorCallbackCall 类型。

然后就是 call.enqueue(new Callback<String>() {...}); 方法了,既然知道此时 call 是 ExecutorCallbackCall 类型,那么看看 ExecutorCallbackCall 的源码

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }
    ...
  }

明显的,这是个装饰模式,ExecutorCallbackCall 在创建时,传递了两个参数给构造方法,new ExecutorCallbackCall<>(callbackExecutor, call) 这两个参数类型分别对应 MainThreadExecutor 和 OkHttpCall 对象类型,所以 ExecutorCallbackCall 中的成员变量 callbackExecutor 是 MainThreadExecutor,是用 Handler 来切换线程的,delegate 是 OkHttpCall 类型,是来构建请求头和请求体的,注意 enqueue() 方法,先对 callback 进行非空判断,然后执行代理 delegate 的 enqueue() 方法,

OkHttpCall:

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

    okhttp3.Call call;
    Throwable failure;
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

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

首先是调用 createRawCall() 生成一个 call 对象,如果生成的过程中抛出了异常,则创建 failure 对象,接下来先校验 failure 对象不为空,则直接执行失败方法的回调;如果接口被取消了,则里也是取消;然后是 call 执行它对应的 enqueue() 方法,注意,这时候它和回调都是 Okhttp 中的类了,这一步已经把网络请求交割给 Okhttp 了,然后就是它里面的成功和失败的回调了,成功的话会有个 parseResponse() 方法来封装得到的结果,转换类型。回调执行后,就回到了 ExecutorCallbackCall 中的 delegate 设置的回调中,在它的回调中,用 callbackExecutor 切换到UI线程,然后就回调到了 retrofitTest() 例子中对 call 设置的回到了,这里我们可以做自己的业务逻辑,再说一遍,此时就是UI线程了。大体流程清楚了,再来看看请求的细节,先看 createRawCall() 方法

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

ServiceMethod:

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

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }

RequestBuilder 是一个转换封装请求头、请求体的类,感兴趣的可以看看,助理主要是 ParameterHandler 数组,通过for循环,执行对象中 apply() 方法,前面讲到了 @Url 和 @Field
注解对应的类型是 ParameterHandler 中内部类 RelativeUrl 和 Query

  static final class RelativeUrl extends ParameterHandler<Object> {
    @Override void apply(RequestBuilder builder, Object value) {
      builder.setRelativeUrl(value);
    }
  }
  
  static final class Query<T> extends ParameterHandler<T> {
    @Override void apply(RequestBuilder builder, T value) throws IOException {
      if (value == null) return; // Skip null values.
      builder.addQueryParam(name, valueConverter.convert(value), encoded);
    }
  }

通过这可以知道,通过 for 循环,把参数添加到了 requestBuilder 对象中,注意 Query 中的参数,name 是 getBlog(@Url String url,@Query("type") int type) 中 @Query("type")括号中的 "type",value 是 retrofitTest() 中传递的参数 "abc",valueConverter 指的是前面 parseParameterAnnotation()方法中获取的StringConverter 对象,此时它方法中返回的值是本身

 static final class StringConverter implements Converter<String, String> {
    static final StringConverter INSTANCE = new StringConverter();

    @Override public String convert(String value) throws IOException {
      return value;
    }
  }

RequestBuilder 添加参数最终还是通过 HttpUrl 、 FormBody 等,这个和 Okhttp 里面的 Request 里面的原理是相同的,最终通过 build() 方法来创建 Request 对象,serviceMethod.callFactory.newCall(request) 中 serviceMethod.callFactory 对应的是 Retrofit 中的 callFactory 属性,也就是 OkHttpClient,它的 newCall() 方法返回的 Call 是 RealCall 类型的对象,所以 call执行enqueue()方法也就对应 RealCall 的 enqueue() 方法,在 Okhttp 中,用线程池开启线程请求网络接口;看看回调成功的逻辑,是如何转换返回的报文类型,关键是 parseResponse() 方法

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      catchingBody.throwIfCaught();
      throw e;
    }
  }

前面三四行代码是给 rawResponse 中的body对象再包装一层 NoContentResponseBody,然后重新设置进去;获取code码,如果不在200和300之间,则创建一个ResponseBody对象,然后设置到 Response 的静态方法中,生成 Response 对象;如果是 204 或 205,也是静态方法返回 Response 对象,不过此时设置的报文为null; ExceptionCatchingRequestBody 装饰模式
,在它的 source() 方法中,当解读数据时,添加了 ForwardingSource 中间代理层,它的 read() 方法中加了try.catch 异常机制处理,当执行 serviceMethod.toResponse(catchingBody) 方法时会起到作用,serviceMethod 对应StringResponseBodyConverter ,它仅仅是获取 ResponseBody 中的 string(),然后转换为字符串返回,它会触发 bytes() 方法,这个方法触发了 ExceptionCatchingRequestBody 中的 source() 方法及 ForwardingSource 中的 read() 方法。

到此,例子中的讲解就此结束了,各位可以按照这个逻辑,自行阅读以下 pot 请求和同步线程请求。

发布了176 篇原创文章 · 获赞 11 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Deaht_Huimie/article/details/102973444