Retrofit 源码阅读记录

image-20210819152814979

Retrofit 实例化

通过 builder 的模式生成实例。

  • platform:平台类型,以作不同兼容

  • callFactory :用来创建方法调用模型 Call(可异步或同步,有点像 FutureTask,用来获取结果的调用),将方法调用转为 Http 访问。

  • baseUrl:基础地址。 一般代表域名或 IP,标识域名最后必须带\,保证 path 的准确性。如果 host + path 出现两次 \,则会被优化正常模式。

  • converterFactories:序列化反序列化工厂,用来获取 Converter ,每个工厂都有自定义支持的类型;

    当设置 platform 时,会设置内置的 BuiltInConverters,保证基本的类型转换正确性。

    final class BuiltInConverters extends Converter.Factory {
          
          
      @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
          
          
        if (type == ResponseBody.class) {
          
          
          if (Utils.isAnnotationPresent(annotations, Streaming.class)) {
          
          
              // 原样返回
            return StreamingResponseBodyConverter.INSTANCE;
          }
            // 将结果缓存到 buffer 中,避免后续的IO
          return BufferingResponseBodyConverter.INSTANCE;
        }
        if (type == Void.class) {
          
          
            // 用来直接关闭连接,返回 null
          return VoidResponseBodyConverter.INSTANCE;
        }
        return null;
      }
     }
    
  • adapterFactories:调用模型适配器工厂,获取 CallAdapter(支持调用转化为具体的类型),每个工厂都有自定义支持的类型。是 Converter 的更外一层,先将调用执行了,再根据 Converter 转为结果模型。

    Adapter 更关注调用的行为模式。

  • callbackExecutor:调用执行器,是否异步的关键。

  • validateEagerly:是否提前解析和初始化调用方法

默认配置是 OkHttpClient、空的 Executor、默认的返回接口适配器(就是啥也不做,原样返回)、无序列化反序列化器。

public static final class Builder {
    
    
  private Platform platform;
  private okhttp3.Call.Factory callFactory;
  private HttpUrl baseUrl;
  private List<Converter.Factory> converterFactories = new ArrayList<>();
  private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
  private Executor callbackExecutor;
  private boolean validateEagerly;
  public Retrofit build() {
    
    
      if (baseUrl == null) {
    
    
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
    
    
          // 默认就是 OkHttpClient,一家的
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
    
    
          // Java 的话,默认是 NULL
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      // 如果 callbackExecutor != null,那实际是做一层同步转异步调用的封装
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

Platform 保证各平台的适应性,主要通过 load 特殊类会不会报错实现的。

private static Platform findPlatform() {
    
    
  try {
    
    
    Class.forName("android.os.Build");
    if (Build.VERSION.SDK_INT != 0) {
    
    
      return new Android();
    }
  } catch (ClassNotFoundException ignored) {
    
    
  }
  try {
    
    
    Class.forName("java.util.Optional");
    return new Java8();
  } catch (ClassNotFoundException ignored) {
    
    
  }
  try {
    
    
    Class.forName("org.robovm.apple.foundation.NSObject");
    return new IOS();
  } catch (ClassNotFoundException ignored) {
    
    
  }
  return new Platform();
}

主要保证是否需要处理接口 default method、Executor 等。

默认的实现类有 Java、Android、IOS。

image-20210819101521333

接口

在初始化时,就生成一个接口的代理

validateEagerly == true

就会在初始化时,就拉取所有非默认方法来生成 method 的代理(ServiceMethod),并缓存。否则延迟到实际调用实际。

实际的方法调用,先是通过 Okhttp 包装来确保网络调用的处理;然后就会被 CallAdapter (从 Retrofit 里面找是否适用的)包装起来,来进行实际调用(一般就是 OkHttp Client)。

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)) {
    
    
              // 只有 Java 平台才能执行 default 方法
            return platform.invokeDefaultMethod(method, service, proxy, args);
          }
            // 加载方法代理
          ServiceMethod serviceMethod = loadServiceMethod(method);
            // 包装成 Http 调用
          OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // 将调用模型封装为特定的模型,比如 java8 CompletedFuture、rxJava 的响应式等
            // 一般默认是 DefaultCallAdapterFactory,不做任何处理
            // 或自定义线程池情况下,ExecutorCallAdapterFactory 转为异步调用
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}

最后得到可能是你想要的结果,也可能仅仅是一个 Http 调用的封装。这取决于 CallAdapter 的作用。

这样做的目的,我想也是因为在基础 http 请求之外再做一些处理,比如我司使用的 Hystrix 熔断处理。

当然,也可以自定义 Adapter 和 AdapterFactory,在做 Call 的适配时,直接进行调用,并产生业务结果。

JavaAdapter 有点像这样,不过会将结果用 CompletedFuture 返回。

Retrofit-第 1 页

ServiceMethod

对 method 的一层包装,最主要是解析方法上关于 Retrofit 的注解和元数据信息,然后生成一套解析器、转换器等。

实际调用时,将实际参数转为 Http Request;调用成功,再将结果转为具体的业务类型。

Request toRequest(Object... args) throws IOException {
    
    }
T toResponse(ResponseBody body) throws IOException {
    
    }
static final class Builder<T> {
    
    
   // 基础属性, 借助 retrofit 的一些设置,以及 Method 的其他信息
  final Retrofit retrofit;
  final Method method;
  final Annotation[] methodAnnotations;
  final Annotation[][] parameterAnnotationsArray;
  final Type[] parameterTypes;
// 解析方法的元数据
  Type responseType;
  boolean gotField;
  boolean gotPart;
  boolean gotBody;
  boolean gotPath;
  boolean gotQuery;
  boolean gotUrl;
  String httpMethod;
  boolean hasBody;
  boolean isFormEncoded;
  boolean isMultipart;
  String relativeUrl;
  Headers headers;
  MediaType contentType;
  Set<String> relativeUrlParamNames;
  ParameterHandler<?>[] parameterHandlers;
  Converter<ResponseBody, T> responseConverter;
  CallAdapter<?> callAdapter;

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

build

实例化方式也是 Builder 模式。

public ServiceMethod build() {
    
    
   // 根据返回类型和注解,在 Retrofit 配置的列表中找到匹配的 callAdapter
   // 默认的请求方法返回值都是Call<T>, 可以继承CallAdapter.Factory来实现自定义的返回值类型
  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?");
  }
   // 根据返回类型和注解,在 Retrofit 配置的列表中找到匹配的 converter
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
    
    
      // 处理注解,来填充元数据信息,比如 GET、PUT、isMultipart、isFormEncoded
      // 如果出现不符合的情况,直接报错
    parseMethodAnnotation(annotation);
  }
 // 省略一些异常情况的检查
  。。。。。

  int parameterCount = parameterAnnotationsArray.length;
    // 负责将参数填充到对应 Http 的请求模型中,比如 Body、Header、URLParam等
  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);
}

OkHttpCall

retrofit 通过 Call 接口体现一个方法调用转为 Http 调用,可以是同步调用 execute,也可以是异步调用 enqueue(Callback)。

public interface Call<T> extends Cloneable {
    
    
  Response<T> execute() throws IOException;
  void enqueue(Callback<T> callback);
  Request request();

Callback 其实就是体现出回调,内置成功或失败的处理。

像使用 JavaAdapter 时,结果会被转换为 CompletedFuture。

一般来说,在 retrofit 的默认实现中,有线程池的情况下,会使用 enqueue。

最后得到一个 Call,只要调用执行方法就会产生一次 Http 请求并获取结果了。

Retrofit-第 2 页

构建 Request 和 OkHttp Call
private okhttp3.Call createRawCall() throws IOException {
    
    
    // 像前面说的,通过解析器、转换器等,将参数转为 Request 参数
  Request request = serviceMethod.toRequest(args);
    // 构建 okhttp3 的调用,毕竟使用 OkHttp 请求的。
  okhttp3.Call call = serviceMethod.callFactory.newCall(request);
  if (call == null) {
    
    
    throw new NullPointerException("Call.Factory returned null.");
  }
  return call;
}

public synchronized Request request() {
    
    
    okhttp3.Call call = rawCall;
    if (call != null) {
    
    
      return call.request();
    }
    if (creationFailure != null) {
    
    
      if (creationFailure instanceof IOException) {
    
    
        throw new RuntimeException("Unable to create request.", creationFailure);
      } else {
    
    
        throw (RuntimeException) creationFailure;
      }
    }
    try {
    
    
      return (rawCall = createRawCall()).request();
    } catch (RuntimeException e) {
    
    
      creationFailure = e;
      throw e;
    } catch (IOException e) {
    
    
      creationFailure = e;
      throw new RuntimeException("Unable to create request.", e);
    }
  }
同步 execute
public Response<T> execute() throws IOException {
    
    
  okhttp3.Call call;

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

    if (creationFailure != null) {
    
    
        // 说明之前构建过 Call 和 Request,且失败了
      if (creationFailure instanceof IOException) {
    
    
        throw (IOException) creationFailure;
      } else {
    
    
        throw (RuntimeException) creationFailure;
      }
    }

    call = rawCall;
    if (call == null) {
    
    
      try {
    
    
        call = rawCall = createRawCall();
      } catch (IOException | RuntimeException e) {
    
    
        creationFailure = e;
        throw e;
      }
    }
  }

  if (canceled) {
    
    
    call.cancel();
  }
 // 执行返回结果
  return parseResponse(call.execute());
}
异步 enqueue
public void enqueue(final Callback<T> callback) {
    
    
  if (callback == null) throw new NullPointerException("callback == null");

  okhttp3.Call call;
  Throwable failure;

  synchronized (this) {
    
    
   // 同上

  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();
      }
    }
  });
}
转换结果 parseResponse

将 OkHttp 的 Response 转为 Retrofit 自己的 Response

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

  // Remove the body's source (the only stateful object) so we can pass the response along.
  rawResponse = rawResponse.newBuilder()
      .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
      .build();

  int code = rawResponse.code();
  if (code < 200 || code >= 300) {
    
    
    try {
    
    
      // Buffer the entire body to avoid future I/O.
      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) {
    
    
    // If the underlying source threw an exception, propagate that rather than indicating it was
    // a runtime exception.
    catchingBody.throwIfCaught();
    throw e;
  }
}

Converter、Adapter

可以引入相应的扩展包来支持不同的场景。

比如 Jackson、Gson、FastJson 的 Converter;

比如 支持Java8 CompletedFuture、RxJava 响应式编程 的 Adapter。

Adapter 默认通过返回值类型判断,只要是适配成特定的类型。这个类型不是业务结果模型,而是调用模型。

一般都是 Call,而像 Java8 就是 CompletedFuture,获取结果就通过 CompletedFuture.get。

猜你喜欢

转载自blog.csdn.net/jiangxiayouyu/article/details/119803290