- 概述
- 基本使用
- 源码分析
- 1. 构造 Retrofit 对象
- 2. 创建服务接口对象
- 3. 解析服务方法上的注解
- 通过服务方法发起网络请求
- CallAdapter
- Converter
- ParameterHandler
- OkHttpCall
- 总结
- 参考
源码基于 com.squareup.retrofit2:retrofit:2.9.0。
概述
- Builder 模式构建;
- 动态代理;
- 自定义注解;
- 默认只能将响应体转换为 OkHttp 中的 ResponseBody。
Retrofit 只负责生产能做网络请求的工作对象,他有点像一个工厂,只提供产品,工厂本身不处理网络请求,产品才能处理网络请求。
基本使用
public interface GitHubService {
@GET("/users/{user}")
Call getUser(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call userCall = service.getUser("square");
userCall.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
GitHubUser user = response.body();
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
源码分析
Retrofit 整体流程如下:
1. 构造 Retrofit 对象
// Retrofit.java
public static final class Builder {
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
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();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List converterFactories =
new ArrayList<>(1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
}
- url 不能为空;
- callFactory 默认为 OkHttpClient;
- 支持 Java 和 Android 平台。
// Platform.java
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android()
: new Platform(true);
}
2. 创建服务接口对象
// Retrofit.java
public T create(final Class 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);
}
});
}
private void validateServiceInterface(Class> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class> candidate = check.removeFirst();
if (candidate.getTypeParameters().length != 0) {
// ...
throw new IllegalArgumentException(message.toString());
}
// 检查父接口
Collections.addAll(check, candidate.getInterfaces());
}
//是否提前加载服务方法
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
- 服务类必须是接口,且不支持泛型;
- 判断是否预加载服务方法;
- 通过
动态代理
实例化服务接口对象。
3. 解析服务方法上的注解
// Retrofit.java
public T create(final Class 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);
}
});
}
ServiceMethod> loadServiceMethod(Method method) {
ServiceMethod> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
通过动态对象调用服务方法。
- 服务方法存在,直接返回;
- 服务方法不存在,解析服务方法,并添加到缓存。
// ServiceMethod.java
static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
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.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
- 根据注解解析出请求方法,相对地址和请求头等数据,并包装成 RequestFactory;
- 服务方法返回类型不能是 void,类型变量和通配符类型;
- 返回 ServiceMethod 实例。
// RequestFactory.java
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 参数检查
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// 必要的数据合法性检查
return new RequestFactory(this);
}
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
isFormEncoded = true;
}
}
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
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);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
- 根据具体的注解类型解析出数据;
// HttpServiceMethod.java
static HttpServiceMethod parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// ...
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// Kotlin 协程方法
} else {
// Call,Observable
adapterType = method.getGenericReturnType();
}
// 查找能处理此请求的 CallAdapter
CallAdapter callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// Call 中的 GitHubUser
Type responseType = callAdapter.responseType();
// 查找能处理此请求的响应转换器
Converter responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
// ...
} else {
// ...
}
}
- 适配 CallAdapter;
- 查找能处理此返回类型的 ConverterFactory。默认的 BuiltInConverters 只能处理 ResponseBody 和 Void 类型;
- 返回 CallAdapted 对象。
通过服务方法发起网络请求
abstract class HttpServiceMethod extends ServiceMethod {
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call call, Object[] args);
static final class CallAdapted extends HttpServiceMethod {
private final CallAdapter callAdapter;
@Override
protected ReturnT adapt(Call call, Object[] args) {
// DefaultCallAdapterFactory$CallAdapter
return callAdapter.adapt(call);
}
}
}
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
@Override
public @Nullable CallAdapter, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call or Call extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter
- 适配成 retrofit2.Call
、Single 等; - 通过 retrofit2.OkHttpCall 发起 http 请求;
- 响应消息回调。
CallAdapter
负责把 Retrofit 中执行网络请求的 Call 对象,转换为接口中定义的 Call 对象(eg:Observable< User >,Flowable< User >)。
public interface CallAdapter {
Type responseType();
T adapt(Call call);
abstract class Factory {
public abstract @Nullable CallAdapter, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
Retrofit 默认实现了两个 CallAdapter:
- DefaultCallAdapterFactory
- CompletableFutureCallAdapterFactory
Converter
负责把服务器返回的数据(JSON、XML、二进制或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象。
public interface Converter {
T convert(F value) throws IOException;
abstract class Factory {
public @Nullable Converter responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
public @Nullable Converter, RequestBody> requestBodyConverter(
Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public @Nullable Converter, String> stringConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
Converter.Factory 的默认实现类有 BuiltInConverters
和 OptionalConverterFactory
。
final class BuiltInConverters extends Converter.Factory {
@Override
public @Nullable Converter responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
}
ParameterHandler
负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数。
OkHttpCall
final class OkHttpCall implements Call {
@Override
public void enqueue(final Callback callback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
call = rawCall = createRawCall();
}
}
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
}
});
}
Response 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();
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
}
}
总结
- 构造 retrofit,核心参数有 baseurl,callFactory(默认 okhttpclient),converterFactories,adapterFactories 和 excallbackExecutor。
- 通过 Retrofit#create() 方法获取接口的实现类,运用了 Java 的动态代技术。
- 调用服务方法时会先实例化 ServiceMethod。ServiceMethod 通过解析服务方法上的注解
在 invoke 方法内部,拿到我们所声明的注解以及实参等,构造 ServiceMethod。ServiceMethod 中解析了大量的信息,最后可以通过 toRequest 构造出 okhttp3.Request 对象。有了 okhttp3.Request 对象就可以很自然的构建出 okhttp3.call,最后 calladapter 对 Call 进行装饰返回。
拿到 Call 就可以执行 enqueue 或者 execute 方法了
responseBodyConverter 主要是对应@Body 注解,完成 ResponseBody 到实际的返回类型的转化,这个类型对应 Call< XXX >里面的泛型,其实@Part 等注解也会需要 responseBodyConverter,只不过我们的参数类型都是 RequestBody,由默认的 converter 处理了。
requestBodyConverter 完成对象到 RequestBody 的构造。
一定要注意,检查 type 如果不是自己能处理的类型,记得 return null (因为可以添加多个,你不能处理 return null ,还会去遍历后面的 converter).
参考
[1] 从架构角度看 Retrofit 的作用、原理和启示
[2] 拆轮子系列:拆 Retrofit