源码分析
Retrofit 是 square 公司出品的基于 okhttp 的适用于 Android 和 JVM 的类型安全的 HTTP 客户端,它对网络请求进行了封装真正发起网络请求的还是 okhttp 拿到响应之后再转发给 retrofit,先看一下 retrofit 的基本使用方式
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");
List<Contributor> contributors = call.execute().body();
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
大概分几步,先创建 Retrofit 对象,再获取一个 API 接口实例然后调用 API 接口实例得到 Call 对象,最后调用 Call 的 execute 方法得到响应结果,接下来一步步看一下
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 如果不设置 callFactory 默认 OkHttpClient 也可以通过 client 设置自己的 OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// Executor 对象用于对回调进行切换线程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 默认实现是 retrofit2.Platform.Android.MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
// this.callAdapterFactories 是通过 addCallAdapterFactory 添加的 CallAdapter.Factory 对象用来适配不同的 API 方法返回值类型
// 比如 Retrofit 自己的 Call 比如 RxJava 的 Observable
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// 默认添加 DefaultCallAdapterFactory 用来处理返回值是 Call 类型的方法
// 如果支持 Java8 还会添加一个 CompletableFutureCallAdapterFactory 处理返回值是 CompletableFuture 的方法不支持则不添加
// 如果需要处理其他类型需要添加相应的 CallAdapter.Factory 来处理
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 与上面的 callAdapterFactories 差不多
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 添加默认的转换器工厂
converterFactories.add(new BuiltInConverters());
// 用户自己添加的转换器工厂
converterFactories.addAll(this.converterFactories);
// 默认的转换器工厂
// 如果支持 Java8 添加一个 OptionalConverterFactory 处理 Optional 不支持则为空
converterFactories.addAll(platform.defaultConverterFactories());
// 创建 Retrofit 对象
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
通过构建者模式创建 Retrofit 对象,其中两个需要注意的是 CallAdapter.Factory 和 Converter.Factory。CallAdapter.Factory 用来创建 CallAdapter 对象,CallAdapter 用来将 Call 转换为相应的类型
public interface CallAdapter<R, T> {
// 获取方法定义的返回值类型对于上面的例子就是 List<Contributor>
Type responseType();
// 将原始类型 Call 转换为其他类型比如 Observable 比如 Deferred
T adapt(Call<R> call);
abstract class Factory {
// 根据返回值类型获取 CallAdapter 对象
public abstract @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
// 获取泛型参数上界,比如 <? extends Runnable> 返回 Runnable
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
// 获取指定类型的原始类型,比如 List<? extends Runnable>} 返回 List.class
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
Retrofit 通过 CallAdapter 来将原始的 Call 转换为其他返回值类型,如果需要支持其他的返回值类型则需要在创建 Retrofit 对象时传入对应的 CallAdapter.Factory 实现,再来看看Converter.Factory
public interface Converter<F, T> {
@Nullable
T convert(F value) throws IOException;
abstract class Factory {
// 获取一个 Converter 用于将 ResponseBody 转换为指定的类型
// 指定的类型是 CallAdapter 接口里面的 responseType() 函数返回的类型
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
// 获取一个 Converter 将方法参数转换为 RequestBody 用于转换被注解 @Body, @Part 和 @PartMap 标记的类型
public @Nullable Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
return null;
}
// 获取一个 Converter 将方法参数转换为 String 用于转换除 @Body, @Part 和 @PartMap 注解标记的类型
public @Nullable Converter<?, String> stringConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
}
}
Converter.Factory 用于创建 Converter 对象,Converter 用于对注解参数和接口响应进行转换为相应的类型,接着回去继续看主流程,调用 Retrofit 的 create 传入定义的接口
private void validateServiceInterface(Class<?> service) {
// 如果不是接口抛出异常
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque<Class<?>> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class<?> candidate = check.removeFirst();
// 如果接口有泛型参数抛出异常
if (candidate.getTypeParameters().length != 0) {
StringBuilder message =
new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ").append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
Collections.addAll(check, candidate.getInterfaces());
}
// 如果设置 validateEagerly 为 true 则会提前校验所有接口方法
// 可在测试环境开启
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
public <T> T create(final Class<T> service) {
// 接口校验
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable 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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
create 方法中先对接口和接口方法进行校验然后通过 Java 自带的动态代理机制生成实现接口的对象字节码然后通过反射创建代理对象
package com.sun.proxy;
import com.example.retrofit.SimpleService.GitHub;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import retrofit2.Call;
public final class $Proxy0 extends Proxy implements GitHub {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Call contributors(String var1, String var2) throws {
try {
return (Call)super.h.invoke(this, m3, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.example.retrofit.SimpleService$GitHub").getMethod("contributors", Class.forName("java.lang.String"), Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
以上代码使用 sun.misc.ProxyGenerator#generateProxyClass(java.lang.String, java.lang.Class<?>[], int) 生成,当调用代理对象的方法时就会转发给调用 retrofit2.Retrofit#create 时传入的 InvocationHandler 对象的 invoke 方法然后解析方法上的注解装配请求,如果是默认方法调用 invokeDefaultMethod(Java8)否则调用 loadServiceMethod(method).invoke(args)
ServiceMethod<?> loadServiceMethod(Method method) {
// 如果有缓存直接使用缓存,由于反射性能较差所以使用了缓存保证一个接口的一个方法只反射一次
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 解析方法注解返回 ServiceMethod 对象加入缓存,下次再次调用此方法使用缓存
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 解析方法注解、方法参数注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 方法返回值类型 Call<List<Contributor>>
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 返回 HttpServiceMethod 对象(最终返回的是 ServiceMethod 的子类 CallAdapted 对象)
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
最后返回的是 ServiceMethod 的子类 CallAdapted 对象,先看一下对方法注解的解析
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 方法注解
this.methodAnnotations = method.getAnnotations();
// 方法参数类型
this.parameterTypes = method.getGenericParameterTypes();
// 方法参数注解,是一个二维数组第一维是注解位置,第二维是注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory build() {
// 解析方法的注解,针对上面的例子只有一个 GET 注解,所以等下就只看对 GET 注解的解析
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 有几个注解就会创建几个 ParameterHandler 对象
// ParameterHandler 是对所有参数注解的封装,每一个方法注解都会对应创建一个 ParameterHandler 对象,
// 创建请求的时候会遍历所有的 ParameterHandler 传入 RequestBuilder 对象调用其 apply 方法对请求进行组装
// 最后创建一个 okhttp 的 Request.Builder 对象,调用 Request.Builder 对象的 build 方法创建一个 okhttp 的请求(Request)
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
// 解析方法参数注解返回一个 ParameterHandler 对象(下面分析)
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// 最终返回一个 RequestFactory 对象它包含创建一个请求的所有信息
return new RequestFactory(this);
}
}
同样是通过构建者模式创建 RequestFactory 对象,RequestFactory 的作用就是解析方法和参数注解记录接口请求信息用于创建一个 okhttp3.Request 对象,看一下其中对注解的解析过程
// 解析方法注解
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);
}
// 省略了解析其他注解的 case
}
// GET 请求 hasBody 为 false
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError(
method,
"Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod,
httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// 处理注解中路径中的查询参数
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(
method,
"URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.",
queryParams);
}
}
// 得到 "/repos/{owner}/{repo}/contributors"
this.relativeUrl = value;
// 拿到其中花括号包裹的 owner 和 repo 之后会对 Path 注解中拿到的 value 进行校验
this.relativeUrlParamNames = parsePathParameters(value);
}
// 解析参数注解
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
// 解析参数注解,所有的 Retrofit 中用于参数的注解最后都会映射为一个 ParameterHandler 的子类对象
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
// 如果不是 Retrofit 中的注解,继续解析下一个
if (annotationAction == null) {
continue;
}
// 如果在一个参数上找到多个 Retrofit 的注解抛出异常
if (result != null) {
throw parameterError(
method, p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
}
// 对协程的处理
if (result == null) {
if (allowContinuation) {
try {
if (Utils.getRawType(parameterType) == Continuation.class) {
// 最后一个参数是 Continuation 类型标记是 suspend 函数
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
// 省略了对其他方法注解的处理
if (annotation instanceof Path) {
validateResolvableType(p, type);
if (gotQuery) {
throw parameterError(method, p, "A @Path parameter must not come after a @Query.");
}
if (gotQueryName) {
throw parameterError(method, p, "A @Path parameter must not come after a @QueryName.");
}
if (gotQueryMap) {
throw parameterError(method, p, "A @Path parameter must not come after a @QueryMap.");
}
if (gotUrl) {
throw parameterError(method, p, "@Path parameters may not be used with @Url.");
}
if (relativeUrl == null) {
throw parameterError(
method, p, "@Path can only be used with relative url on @%s", httpMethod);
}
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
// 对 Path 注解进行校验如果与从路径解析的占位名字不一样则抛出异常
validatePathName(p, name);
// 默认是使用内置的 retrofit2.BuiltInConverters.ToStringConverter.INSTANCE 将参数转换成 String 类型
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
// 返回一个 ParameterHandler 的内部类(同时也是 ParameterHandler 的子类) ParameterHandler.Path 对象,
return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
}
return null; // Not a Retrofit annotation.
}
private void validatePathName(int p, String name) {
if (!PARAM_NAME_REGEX.matcher(name).matches()) {
throw parameterError(
method,
p,
"@Path parameter name must match %s. Found: %s",
PARAM_URL_REGEX.pattern(),
name);
}
// 对 Path 注解进行校验如果与从路径解析的占位名字不一样则抛出异常
if (!relativeUrlParamNames.contains(name)) {
throw parameterError(method, p, "URL \"%s\" does not contain \"{%s}\".", relativeUrl, name);
}
}
到这里就完成了对方法的注解和方法的参数注解的解析,接下来要去创建 ServiceMethod 对象了
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 根据最后一个参数是不是 Continuation 类型判断是否是 suspend 函数
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// 省略代码
} else {
// 获取方法返回类型 Call<List<Contributor>>
adapterType = method.getGenericReturnType();
}
// 遍历 Retrofit 中配置的所有 CallAdapter.Factory 根据 adapterType 类型获取 CallAdapter 对象
// 这里拿到的是 retrofit2.DefaultCallAdapterFactory 中的匿名内部类
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// List<Contributor>
Type responseType = callAdapter.responseType();
// 省略代码
// 在添加 Converter.Factory 时是先添加的内置的 BuiltInConverters 又添加的 GsonConverterFactory 并且 BuiltInConverters 只处理了 ResponseBody、Void 和 Unit 类型
// 所以这里会拿到 Converter.Factory:retrofit2.converter.gson.GsonConverterFactory
// Converter:retrofit2.converter.gson.GsonResponseBodyConverter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 不是 Kotlin suspend 函数所以直接创建 CallAdapted 对象
// 参数分别是 RequestFactory 对象(包含方法注解信息)
// callFactory 是 OkHttpClient 对象
// responseConverter 是 retrofit2.converter.gson.GsonResponseBodyConverter 对象
// callAdapter 是 retrofit2.DefaultCallAdapterFactory 中的匿名内部类
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
最后返回的是 ServiceMethod 的子类 CallAdapted 对象然后调用父类的 invoke 方法,创建 OkHttpCall 对象紧接着调用抽象方法 adapt
// retrofit2.HttpServiceMethod
@Override
final @Nullable ReturnT invoke(Object[] args) {
// 创建 OkHttpCall 对象参数分别是保存方法注解信息的 requestFactory
// 调用方法的参数 args
// callFactory 就是 OkHttpClient
// 对网络响应转化的 responseConverter GsonResponseBodyConverter
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
// retrofit2.HttpServiceMethod.CallAdapted
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// 直接转发给了 callAdapter 这里的 callAdapter 就是上面提到传入的
// retrofit2.DefaultCallAdapterFactory 中的匿名类
// 传入的参数是 call retrofit2.OkHttpCall.OkHttpCall
return callAdapter.adapt(call);
}
}
最后调用了创建 CallAdapted 时传入的 retrofit2.DefaultCallAdapterFactory 中的匿名类,看一下这个匿名内部类
// retrofit2.DefaultCallAdapterFactory#get
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 只处理原始类型是 Call 的方法
if (getRawType(returnType) != Call.class) {
return null;
}
// 如果没有泛型参数抛出异常
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
// 获取第一个泛型参数的上界 List<Contributor>
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 可以通过设置 SkipCallbackExecutor 注解跳过对回调方法切换线程
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
// 本例中没有设置 SkipCallbackExecutor 注解
// 如果在 Java 平台会返回 null 在 Android 平台会返回 MainThreadExecutor 把回调切换到主线程
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
到这一步就通过调用代理对象的地方返回了一个 ExecutorCallbackCall 对象(Android 平台)然后接着调用 execute 进行同步请求,同步请求没有接口回调也就没有切换线程直接将请求转发给了 OkHttpCall
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
// 获取 okhttp 中的 Call 对象,最后使用它来发送网络请求
call = getRawCall();
}
if (canceled) {
call.cancel();
}
// 发送网络请求,解析接口响应
return parseResponse(call.execute());
}
private okhttp3.Call getRawCall() throws IOException {
try {
return rawCall = createRawCall();
} catch (RuntimeException | Error | IOException e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
private okhttp3.Call createRawCall() throws IOException {
// requestFactory.create(args) 返回一个 okhttp3.Request 对象
// callFactory.newCall 返回一个 okhttp3.Call(同步请求是 okhttp3.RealCall)
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
okhttp3.Request create(Object[] args) throws IOException {
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
// ParameterHandler 是方法参数中 Retrofit 注解映射成的对象,如果与参数个数不一致则抛出异常
if (argumentCount != handlers.length) {
throw new IllegalArgumentException(
"Argument count ("
+ argumentCount
+ ") doesn't match expected count ("
+ handlers.length
+ ")");
}
// 创建一个 RequestBuilder 对象
RequestBuilder requestBuilder =
new RequestBuilder(
httpMethod,
baseUrl,
relativeUrl,
headers,
contentType,
hasBody,
isFormEncoded,
isMultipart);
// suspend 函数最后一个参数不处理
if (isKotlinSuspendFunction) {
argumentCount--;
}
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
// 调用 ParameterHandler 的 apply 对 requestBuilder 进行组装
handlers[p].apply(requestBuilder, args[p]);
}
// 通过 get 方法拿到 okhttp 的 okhttp3.Request.Builder 对象,调用 build 拿到一个 okhttp3.Request 对象,它是最终用于发送网络请求的
return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
}
// 看一下上面提到的本例中的 Path 注解的处理
static final class Path<T> extends ParameterHandler<T> {
private final Method method;
private final int p;
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
Path(Method method, int p, String name, Converter<T, String> valueConverter, boolean encoded) {
this.method = method;
this.p = p;
this.name = Objects.requireNonNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) {
throw Utils.parameterError(
method, p, "Path parameter \"" + name + "\" value must not be null.");
}
// 调用 RequestBuilder 的 addPathParam 方法
// valueConverter 默认对 value 调用 toString 用户也可以自己定义 Converter 根据 type 进行处理
builder.addPathParam(name, valueConverter.convert(value), encoded);
}
}
void addPathParam(String name, String value, boolean encoded) {
if (relativeUrl == null) {
// The relative URL is cleared when the first query parameter is set.
throw new AssertionError();
}
String replacement = canonicalizeForPath(value, encoded);
// 对从方法注解 GET 中解析到的相对路径中的占位进行替换
String newRelativeUrl = relativeUrl.replace("{" + name + "}", replacement);
if (PATH_TRAVERSAL.matcher(newRelativeUrl).matches()) {
throw new IllegalArgumentException(
"@Path parameters shouldn't perform path traversal ('.' or '..'): " + value);
}
// 新的真实的相对路径
relativeUrl = newRelativeUrl;
}
RequestFactory 保存有解析方法注解得到的信息创建 RequestBuilder 对象再遍历解析方法参数注解得到的 ParameterHandler 数组调用其 retrofit2.ParameterHandler.Path#apply 方法对 RequestBuilder 进行装配,最后调用 RequestBuilder 的 get 方法拿到 okhttp3.Request.Builder 对象,构建者模式最终拿到一个 okhttp3.Request 对象传给 callFactory(OkHttpClient)得到一个 okhttp3.Call 对象(okhttp3.RealCall)然后执行网络请求,对接口响应进行解析
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// 先拿到响应的 body
ResponseBody rawBody = rawResponse.body();
// 为 rawResponse 重新赋值给一个没有内容的 ResponseBody
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) {
rawBody.close();
return Response.success(null, rawResponse);
}
// 一个捕获了异常的 ResponseBody
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 这里的 responseConverter 是 GsonResponseBodyConverter 将网络响应转换为对应的实体,这样就完成了整个请求过程同步请求流程就结束了
T body = responseConverter.convert(catchingBody);
// 返回成功的 Response
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;
}
}
上面是一个返回类型是 Call 同步请求的例子,再来看一个返回值类型是 Observable 异步请求的例子,首先在创建 Retrofit 实例的时候需要添加 RxJava2CallAdapterFactory 然后要把方法的返回值从 Call 改成 Observable
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl(API_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHub github = retrofit.create(GitHub.class);
Observable<List<Contributor>> observable = github.contributors("square", "retrofit");
observable.subscribe(new ResponseObserver<List<Contributor>>() {
@Override
public void onNext(List<Contributor> contributors) {
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
});
这个时候在 retrofit2.HttpServiceMethod#parseAnnotations 中通过 retrofit2.HttpServiceMethod#createCallAdapter 拿到的 CallAdapter 是 RxJava2CallAdapter 看一下它的代码
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
// 构造方法是私有的通过静态方法创建对象
// scheduler 用来切换线程 isAsync 表示是否是异步请求
private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
// 如果是 Completable 类型创建 RxJava2CallAdapter 对象返回
if (rawType == Completable.class) {
return new RxJava2CallAdapter(
Void.class, scheduler, isAsync, false, true, false, false, false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
// 如果不是 RxJava2 支持的类型则返回 null
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
// 如果返回值不是泛型抛出异常
if (!(returnType instanceof ParameterizedType)) {
String name =
isFlowable ? "Flowable" : isSingle ? "Single" : isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(
name
+ " return type must be parameterized"
+ " as "
+ name
+ "<Foo> or "
+ name
+ "<? extends Foo>");
}
// 获取第一个泛型参数的上界
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
// 也可以处理 Observable<Response<T>> 类型的返回值
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException(
"Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
// 也可以处理 Observable<Result<T>> 类型的返回值
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException(
"Result must be parameterized" + " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
// 返回 RxJava2CallAdapter 对象
return new RxJava2CallAdapter(
responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
}
}
接下来还跟同步请求一样创建 CallAdapted 对象只不过这次传入的 callAdapter 参数是 RxJava2CallAdapter 对象然后调用它的 adapt 方法将 Call 转换成 Observable 看一下代码
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
// 去掉 Observable 后的返回值类型,比如 Observable<T> 中的 T
private final Type responseType;
private final @Nullable Scheduler scheduler;
// 是否是异步请求
private final boolean isAsync;
private final boolean isResult;
// 表示 Observable<T> 中的 T 不是 Result 和 Response 就是需要的类型
private final boolean isBody;
// 返回值原始类型是不是 Flowable
private final boolean isFlowable;
// 返回值原始类型是不是 Single
private final boolean isSingle;
// 返回值原始类型是不是 Maybe
private final boolean isMaybe;
// 返回值原始类型是不是 Completable
private final boolean isCompletable;
RxJava2CallAdapter(
Type responseType,
@Nullable Scheduler scheduler,
boolean isAsync,
boolean isResult,
boolean isBody,
boolean isFlowable,
boolean isSingle,
boolean isMaybe,
boolean isCompletable) {
this.responseType = responseType;
this.scheduler = scheduler;
this.isAsync = isAsync;
this.isResult = isResult;
this.isBody = isBody;
this.isFlowable = isFlowable;
this.isSingle = isSingle;
this.isMaybe = isMaybe;
this.isCompletable = isCompletable;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public Object adapt(Call<R> call) {
// 异步请求返回 CallEnqueueObservable
// call 依然是 OkHttpCall
Observable<Response<R>> responseObservable =
isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
// isBody 为 true 创建 BodyObservable 对象
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
// 最后返回一个 Observable 对象
return RxJavaPlugins.onAssembly(observable);
}
}
最后返回 BodyObservable 对象,并且这个对象持有一个持有 OkHttpCall 对象的 Observable 对象(CallEnqueueObservable),调用 subscribe 方法最后会走到 CallEnqueueObservable 的 subscribeActual 方法
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
private final Call<T> originalCall;
CallEnqueueObservable(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override
protected void subscribeActual(Observer<? super Response<T>> observer) {
Call<T> call = originalCall.clone();
// observer 是 retrofit2.adapter.rxjava2.BodyObservable.BodyObserver
// CallCallback 是一个实现了 retrofit2.Callback 接口的内部类待会再看
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
if (!callback.isDisposed()) {
// 调用 OkHttpCall 的 enqueue 方法
call.enqueue(callback);
}
}
}
最终会调用 OkHttpCall 的异步请求方法
// 传入的是上面提到的内部类 retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
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) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 使用 okhttp 的 call 发送异步请求然后再 okhttp 的回调中解析请求再使用传入的 callback 回调出去
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 解析请求上面已经分析过了
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
做的事情就是创建 okhttp.call 发送请求解析响应再回调出去
private static final class CallCallback<T> implements Disposable, Callback<T> {
private final Call<?> call;
private final Observer<? super Response<T>> observer;
private volatile boolean disposed;
boolean terminated = false;
CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
this.call = call;
this.observer = observer;
}
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (disposed) return;
try {
// 调用 onNext
observer.onNext(response);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposed) {
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
if (call.isCanceled()) return;
try {
// 调用 onError
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
这样整个异步请求并且支持 Observable 返回值类型的例子就分析完了
总结
Retrofit 的工作流程大概是这样的,
- 通过构建者模式创建 Retrofit 对象并且根据需要添加 CallAdapter.Factory(适配返回值类型)和 Converter.Factory(对请求和响应进行转换)然后调用这个对象的 create 方法传入 API 接口,内部通过动态代理生成字节码反射创建代理对象,当调用这个代理对象的方法时会调用到传入的 InvocationHandler 的 invoke 方法
- 对方法的注解和方法参数的注解进行解析得到一个 RequestFactory 对象,它包含了一个网络请求的所有信息
- 根据方法返回值的原始类型获取合适的 CallAdapter(默认是 DefaultCallAdapterFactory 中的匿名内部类,如果定义的方法返回值是 RxJava 相关类则返回 RxJava2CallAdapterFactory 中的 RxJava2CallAdapter) 再根据返回值的响应类型(Call<T> 或者 Observable<T> 中的 T)获取合适的 Converter(一般是 GsonResponseBodyConverter) 再加上 Retrofit 对象中配置的 callFactory(OkHttpClient)创建一个 CallAdapted 对象
- 调用 CallAdapted 对象的 invoke 方法创建 OkHttpCall 对象,创建 OkHttpCall 对象时传入 4 个参数,第一个是第二步中的 RequestFactory 对象,第二个是调用方法的参数,第三个是 OkHttpClient 对象,第四个一般是 GsonResponseBodyConverter 接着调用 CallAdapted 对象的 adapt 方法使用上一步中的 CallAdapter 对 Call 进行转换,默认依然会返回一个 Call 对象(ExecutorCallbackCall),这个 Call 对象持有 OkHttpCall 对象(这里可以理解成装饰模式,目的是为了把对异步请求的回调切换到主线程中)
- 对于同步请求调用上一步返回的 Call 对象的 execute 方法,内部转发给了持有的 OkHttpCall 对象
- 对于异步请求调用上一步返回的 Call 对象的 enqueue 方法,内部转发给了持有的 OkHttpCall 对象
- 无论是同步还是异步请求都会先通过构造方法中传入的 RequestFactory 对象创建 okhttp3.Request#Request 对象,再通过 OkHttpClient 拿到一个 okhttp3.Call(对于同步请求是 okhttp3.RealCall 异步请求是 okhttp3.RealCall.AsyncCall) 对象用于执行真正的网络请求
- 对网络响应进行解析,先拿到原始的 okhttp3.Response 交给 responseConverter 转换成需要的实体对象,再用这个实体对象和一个没有内容(一次性)的 okhttp3.ResponseBody 创建一个 retrofit2.Response 返回出去(同步请求直接返回,异步请求回调出去)整个流程就结束了
其他
在开发过程中通常有切换 baseUrl 的需求,可以通过给接口方法添加 Headers 注解,然后创建 Retrofit 对象时代理 callFactory(OkHttpClient) 对象拿到 request 的 header 根据 header 的值对 baseUrl 重新设置。或者添加 okhttp 拦截器同样拿到 request 的 header 根据 header 的值对 baseUrl 重新设置
对于网络请求通常需要做一些统一处理,可以仿照 GsonConverterFactory 重写 responseBodyConverter 方法对网络请求响应统一处理
参考与感谢
[破解Retrofit(大佬慕课网的课程因审核问题不能给出链接)]
Retrofit解析系列
Retrofit 动态管理和修改 BaseUrl,从未如此简单