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。
接口
在初始化时,就生成一个接口的代理
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 返回。
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 请求并获取结果了。
构建 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。