一、引言
Retrofit 是 Square 公司开发的一款优秀的类型安全的 HTTP 客户端,在 Android 和 Java 开发中被广泛使用。它通过简洁的接口定义和强大的注解功能,使得开发者能够轻松地进行网络请求。请求执行模块是 Retrofit 的核心部分之一,负责将接口方法的调用转换为实际的 HTTP 请求,并处理响应结果。本文将深入 Retrofit 的源码,详细分析请求执行模块的执行原理。
二、Retrofit 基本使用回顾
在深入源码之前,我们先回顾一下 Retrofit 的基本使用。以下是一个简单的示例:
java
java
// 定义 API 接口
public interface GitHubService {
@GET("users/{user}")
Call<ResponseBody> getUser(@Path("user") String user);
}
// 创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
// 创建 API 接口的代理对象
GitHubService service = retrofit.create(GitHubService.class);
// 调用接口方法
Call<ResponseBody> call = service.getUser("octocat");
// 执行同步请求
try {
Response<ResponseBody> response = call.execute();
if (response.isSuccessful()) {
ResponseBody body = response.body();
// 处理响应体
}
} catch (IOException e) {
e.printStackTrace();
}
// 执行异步请求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
ResponseBody body = response.body();
// 处理响应体
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// 处理请求失败
}
});
从上述代码可以看出,使用 Retrofit 进行网络请求主要包括以下几个步骤:
-
定义 API 接口,使用注解描述请求信息。
-
创建 Retrofit 实例,配置基础 URL 等信息。
-
创建 API 接口的代理对象。
-
调用接口方法,获取
Call
对象。 -
执行同步或异步请求,处理响应结果。
接下来,我们将逐步深入这些步骤背后的源码实现。
三、Retrofit 实例创建
3.1 Retrofit.Builder 类
Retrofit 实例的创建通常使用 Retrofit.Builder
类,该类提供了一系列的配置方法。以下是 Retrofit.Builder
类的部分源码:
java
java
public static final class Builder {
// OkHttp 的请求工厂,用于创建实际的 HTTP 请求
private okhttp3.Call.Factory callFactory;
// 基础 URL
private HttpUrl baseUrl;
// 调用适配器工厂列表,用于将网络请求结果适配为不同的类型
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
// 转换器工厂列表,用于将请求参数和响应结果进行序列化和反序列化
private final List<Converter.Factory> converterFactories = new ArrayList<>();
// 回调执行器,用于将回调切换到指定线程
private Executor callbackExecutor;
// 是否验证服务接口
private boolean validateEagerly;
public Builder() {
// 默认使用 OkHttpClient 作为请求工厂
this(Platform.get());
}
Builder(Platform platform) {
// 添加默认的调用适配器工厂
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
}
// 设置请求工厂
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
// 设置基础 URL
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
// 添加调用适配器工厂
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
// 添加转换器工厂
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
// 设置回调执行器
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
// 是否验证服务接口
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
// 构建 Retrofit 实例
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) {
// 如果没有设置回调执行器,使用平台默认的执行器
callbackExecutor = Platform.get().defaultCallbackExecutor();
}
// 复制调用适配器工厂列表,并添加默认的调用适配器工厂
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(Platform.get().defaultCallAdapterFactories(callbackExecutor));
// 复制转换器工厂列表,并添加默认的转换器工厂
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
converterFactories.add(0, new BuiltInConverters());
return new Retrofit(callFactory, baseUrl, converterFactories, callAdapterFactories,
callbackExecutor, validateEagerly);
}
}
Retrofit.Builder
类的主要作用是配置 Retrofit 实例的各种参数,包括请求工厂、基础 URL、调用适配器工厂、转换器工厂和回调执行器等。在 build()
方法中,会对这些参数进行检查和默认值的设置,最终创建一个 Retrofit
实例。
3.2 Retrofit 类
Retrofit
类是 Retrofit 框架的核心类,它封装了各种配置信息,并提供了创建接口代理对象的方法。以下是 Retrofit
类的部分源码:
java
java
public final class Retrofit {
// OkHttp 的请求工厂
private final okhttp3.Call.Factory callFactory;
// 基础 URL
private final HttpUrl baseUrl;
// 转换器工厂列表
private final List<Converter.Factory> converterFactories;
// 调用适配器工厂列表
private final List<CallAdapter.Factory> callAdapterFactories;
// 回调执行器
private final Executor callbackExecutor;
// 服务方法缓存
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
// 是否验证服务接口
private final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories);
this.callAdapterFactories = unmodifiableList(callAdapterFactories);
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
if (validateEagerly) {
// 如果需要验证服务接口,遍历所有方法并加载服务方法
eagerlyValidateMethods();
}
}
// 获取请求工厂
public okhttp3.Call.Factory callFactory() {
return callFactory;
}
// 获取基础 URL
public HttpUrl baseUrl() {
return baseUrl;
}
// 获取转换器工厂列表
public List<Converter.Factory> converterFactories() {
return converterFactories;
}
// 获取调用适配器工厂列表
public List<CallAdapter.Factory> callAdapterFactories() {
return callAdapterFactories;
}
// 获取回调执行器
public Executor callbackExecutor() {
return callbackExecutor;
}
// 创建 API 接口的代理对象
public <T> T create(final Class<T> service) {
// 验证传入的 service 是否为接口类型
validateServiceInterface(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 {
// 如果调用的是 Object 类的方法,直接调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 如果是默认方法,根据平台进行处理
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 创建 ServiceMethod 对象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 创建 OkHttpCall 对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 通过 CallAdapter 进行适配
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
// 加载服务方法
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 从缓存中获取 ServiceMethod 对象
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
// 再次从缓存中获取 ServiceMethod 对象
result = serviceMethodCache.get(method);
if (result == null) {
// 如果缓存中没有,则创建一个新的 ServiceMethod 对象
result = ServiceMethod.parseAnnotations(this, method);
// 将新创建的 ServiceMethod 对象放入缓存中
serviceMethodCache.put(method, result);
}
}
return result;
}
// 提前验证服务接口的方法
private void eagerlyValidateMethods() {
Platform platform = Platform.get();
for (Method method : getClass().getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
Retrofit
类的主要作用是封装配置信息,并提供 create()
方法用于创建 API 接口的代理对象。在 create()
方法中,会使用 Java 的动态代理机制创建一个实现了指定 API 接口的代理对象,并在 InvocationHandler
的 invoke()
方法中处理接口方法的调用。
四、接口代理对象的创建
4.1 create()
方法
create()
方法是创建接口代理对象的核心方法,以下是该方法的详细分析:
java
java
public <T> T create(final Class<T> service) {
// 验证传入的 service 是否为接口类型
validateServiceInterface(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 {
// 如果调用的是 Object 类的方法,直接调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 如果是默认方法,根据平台进行处理
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 创建 ServiceMethod 对象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 创建 OkHttpCall 对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 通过 CallAdapter 进行适配
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
create()
方法的主要步骤如下:
- 验证接口类型 :调用
validateServiceInterface()
方法验证传入的service
是否为接口类型。
java
java
private void validateServiceInterface(Class<?> service) {
// 检查传入的 service 是否为接口类型
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// 检查接口是否有默认方法,并且平台是否支持默认方法
if (Platform.get().isDefaultMethodProblematic()) {
for (Method method : service.getDeclaredMethods()) {
if (Platform.get().isDefaultMethod(method)) {
throw new IllegalArgumentException(
"@SkipCallbackExecutor annotation is required on methods "
+ "with default implementations when targeting API 24 and lower due "
+ "to an issue with default method dispatch.");
}
}
}
}
-
使用动态代理创建代理对象:使用 Java 的动态代理机制创建一个实现了指定 API 接口的代理对象。
-
实现
InvocationHandler
接口 :在invoke()
方法中处理接口方法的调用。-
如果调用的是
Object
类的方法,直接调用该方法。 -
如果是接口的默认方法,根据平台进行处理。
-
调用
loadServiceMethod()
方法创建ServiceMethod
对象。
-
java
java
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 从缓存中获取 ServiceMethod 对象
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
// 再次从缓存中获取 ServiceMethod 对象
result = serviceMethodCache.get(method);
if (result == null) {
// 如果缓存中没有,则创建一个新的 ServiceMethod 对象
result = ServiceMethod.parseAnnotations(this, method);
// 将新创建的 ServiceMethod 对象放入缓存中
serviceMethodCache.put(method, result);
}
}
return result;
}
- 使用
ServiceMethod
对象和方法参数创建OkHttpCall
对象。 - 调用
serviceMethod.callAdapter.adapt()
方法对OkHttpCall
对象进行适配。
4.2 ServiceMethod.parseAnnotations()
方法
ServiceMethod.parseAnnotations()
方法用于解析 API 接口方法的注解,创建 ServiceMethod
对象。以下是该方法的详细源码和分析:
java
java
static <T, R> ServiceMethod<T, R> parseAnnotations(Retrofit retrofit, Method method) {
// 创建 RequestFactory 对象,用于解析请求相关的注解
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.");
}
// 获取 CallAdapter 对象,用于适配网络请求的结果
CallAdapter<T, R> callAdapter = createCallAdapter(retrofit, method, returnType);
// 获取响应类型
Type responseType = callAdapter.responseType();
if (Utils.hasUnresolvableType(responseType)) {
throw methodError(method, "Call adapter returned a type that contains wildcards: %s",
responseType);
}
// 获取 Converter 对象,用于将响应结果进行反序列化
Converter<ResponseBody, T> responseConverter =
createResponseConverter(retrofit, method, responseType);
// 获取 OkHttp 的请求工厂
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new ServiceMethod<>(requestFactory, callAdapter, responseConverter, callFactory);
}
// 创建 CallAdapter 对象
private static <T, R> CallAdapter<T, R> createCallAdapter(Retrofit retrofit, Method method, Type returnType) {
Annotation[] annotations = method.getAnnotations();
try {
// 遍历调用适配器工厂列表,查找合适的 CallAdapter 工厂
for (CallAdapter.Factory factory : retrofit.callAdapterFactories()) {
CallAdapter<?, ?> adapter = factory.get(returnType, annotations, retrofit);
if (adapter != null) {
// 找到合适的 CallAdapter 工厂,返回其创建的 CallAdapter 对象
return (CallAdapter<T, R>) adapter;
}
}
} catch (RuntimeException e) {
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
throw methodError(method, "Could not locate call adapter for %s.", returnType);
}
// 创建响应转换器对象
private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
// 遍历转换器工厂列表,查找合适的 Converter 工厂
for (Converter.Factory factory : retrofit.converterFactories()) {
Converter<ResponseBody, ?> converter = factory.responseBodyConverter(responseType, annotations, retrofit);
if (converter != null) {
// 找到合适的 Converter 工厂,返回其创建的 Converter 对象
return (Converter<ResponseBody, T>) converter;
}
}
} catch (RuntimeException e) {
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
throw methodError(method, "Could not locate response converter for %s.", responseType);
}
ServiceMethod.parseAnnotations()
方法的主要步骤如下:
- 创建
RequestFactory
对象 :调用RequestFactory.parseAnnotations()
方法解析请求相关的注解,创建RequestFactory
对象。
java
java
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
// 创建 RequestFactory.Builder 对象
return new Builder(retrofit, method).build();
}
// RequestFactory.Builder 类
static final class Builder {
private final Retrofit retrofit;
private final Method method;
private final Annotation[] methodAnnotations;
private final Annotation[][] parameterAnnotationsArray;
private final Type[] parameterTypes;
private HttpUrl baseUrl;
private String httpMethod;
private boolean hasBody;
private boolean isFormEncoded;
private boolean isMultipart;
private String relativeUrl;
private ParameterHandler<?>[] parameterHandlers;
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() {
// 解析方法注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 解析参数注解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(method, p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(method, p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !hasBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
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 PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (hasBody) {
throw methodError(method, "@HEAD method must not have a request body.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
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;
}
// 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);
}
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(method, p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof retrofit2.http.Path) {
retrofit2.http.Path path = (retrofit2.http.Path) annotation;
String name = path.value();
validatePathName(p, name);
// 创建 Path 类型的 ParameterHandler,用于处理路径参数
return new ParameterHandler.Path<>(name,
retrofit.stringConverter(type, annotations));
} else if (annotation instanceof retrofit2.http.Query) {
retrofit2.http.Query query = (retrofit2.http.Query) annotation;
String name = query.value();
// 创建 Query 类型的 ParameterHandler,用于处理查询参数
return new ParameterHandler.Query<>(name,
retrofit.stringConverter(type, annotations), query.encoded());
} else if (annotation instanceof retrofit2.http.QueryMap) {
if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
throw parameterError(method, p, "@QueryMap parameter type must be Map.");
}
Type keyType = Utils.getSupertype(type, Map.class, String.class);
if (keyType != String.class) {
throw parameterError(method, p, "@QueryMap keys must be of type String.");
}
Type valueType = Utils.getSupertype(type, Map.class, Object
四、接口代理对象的创建
4.2 ServiceMethod.parseAnnotations()
方法
4.2.1 parseParameterAnnotation
方法详细解析
java
java
} else if (annotation instanceof retrofit2.http.QueryMap) {
if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
throw parameterError(method, p, "@QueryMap parameter type must be Map.");
}
Type keyType = Utils.getSupertype(type, Map.class, String.class);
if (keyType != String.class) {
throw parameterError(method, p, "@QueryMap keys must be of type String.");
}
Type valueType = Utils.getSupertype(type, Map.class, Object.class);
// 创建 QueryMap 类型的 ParameterHandler,用于处理查询参数映射
return new ParameterHandler.QueryMap<>(
retrofit.stringConverter(valueType, annotations),
((retrofit2.http.QueryMap) annotation).encoded());
} else if (annotation instanceof retrofit2.http.Header) {
retrofit2.http.Header header = (retrofit2.http.Header) annotation;
String name = header.value();
// 创建 Header 类型的 ParameterHandler,用于处理请求头参数
return new ParameterHandler.Header<>(name,
retrofit.stringConverter(type, annotations));
} else if (annotation instanceof retrofit2.http.HeaderMap) {
if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
throw parameterError(method, p, "@HeaderMap parameter type must be Map.");
}
Type keyType = Utils.getSupertype(type, Map.class, String.class);
if (keyType != String.class) {
throw parameterError(method, p, "@HeaderMap keys must be of type String.");
}
Type valueType = Utils.getSupertype(type, Map.class, Object.class);
// 创建 HeaderMap 类型的 ParameterHandler,用于处理请求头参数映射
return new ParameterHandler.HeaderMap<>(
retrofit.stringConverter(valueType, annotations));
} else if (annotation instanceof retrofit2.http.Field) {
if (!isFormEncoded) {
throw parameterError(method, p, "@Field parameters can only be used with form encoding.");
}
retrofit2.http.Field field = (retrofit2.http.Field) annotation;
String name = field.value();
// 创建 Field 类型的 ParameterHandler,用于处理表单字段参数
return new ParameterHandler.Field<>(name,
retrofit.stringConverter(type, annotations), field.encoded());
} else if (annotation instanceof retrofit2.http.FieldMap) {
if (!isFormEncoded) {
throw parameterError(method, p, "@FieldMap parameters can only be used with form encoding.");
}
if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
throw parameterError(method, p, "@FieldMap parameter type must be Map.");
}
Type keyType = Utils.getSupertype(type, Map.class, String.class);
if (keyType != String.class) {
throw parameterError(method, p, "@FieldMap keys must be of type String.");
}
Type valueType = Utils.getSupertype(type, Map.class, Object.class);
// 创建 FieldMap 类型的 ParameterHandler,用于处理表单字段参数映射
return new ParameterHandler.FieldMap<>(
retrofit.stringConverter(valueType, annotations),
((retrofit2.http.FieldMap) annotation).encoded());
} else if (annotation instanceof retrofit2.http.Part) {
if (!isMultipart) {
throw parameterError(method, p, "@Part parameters can only be used with multipart encoding.");
}
retrofit2.http.Part part = (retrofit2.http.Part) annotation;
String name = part.value();
if (name.isEmpty()) {
return new ParameterHandler.Part<>();
}
MediaType mediaType = null;
if (!"*/*".equals(name)) {
try {
mediaType = MediaType.get(name);
} catch (IllegalArgumentException e) {
throw parameterError(method, p, "Malformed media type: %s", name);
}
}
// 创建 Part 类型的 ParameterHandler,用于处理多部分请求的部分数据
return new ParameterHandler.Part<>(name, mediaType,
retrofit.stringConverter(type, annotations));
} else if (annotation instanceof retrofit2.http.PartMap) {
if (!isMultipart) {
throw parameterError(method, p, "@PartMap parameters can only be used with multipart encoding.");
}
if (!Map.class.isAssignableFrom(Utils.getRawType(type))) {
throw parameterError(method, p, "@PartMap parameter type must be Map.");
}
Type keyType = Utils.getSupertype(type, Map.class, String.class);
if (keyType != String.class) {
throw parameterError(method, p, "@PartMap keys must be of type String.");
}
Type valueType = Utils.getSupertype(type, Map.class, Object.class);
// 创建 PartMap 类型的 ParameterHandler,用于处理多部分请求的部分数据映射
return new ParameterHandler.PartMap<>(
retrofit.stringConverter(valueType, annotations));
} else if (annotation instanceof retrofit2.http.Body) {
if (hasBody) {
// 创建 Body 类型的 ParameterHandler,用于处理请求体
return new ParameterHandler.Body<>(retrofit.requestBodyConverter(type, annotations, methodAnnotations));
}
throw parameterError(method, p, "@Body parameters cannot be used with HTTP methods "
+ "that do not have a request body (e.g., GET, HEAD).");
} else if (annotation instanceof retrofit2.http.Tag) {
// 创建 Tag 类型的 ParameterHandler,用于设置请求标签
return new ParameterHandler.Tag<>(type);
}
return null;
}
parseParameterAnnotation
方法会根据不同的注解类型创建相应的 ParameterHandler
对象。这些 ParameterHandler
对象负责处理接口方法参数在请求中的不同使用方式,例如将参数作为路径参数、查询参数、请求头参数、表单字段参数、多部分请求数据等。
4.2.2 build
方法总结
java
java
RequestFactory build() {
// 解析方法注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 解析参数注解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(method, p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(method, p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !hasBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
return new RequestFactory(this);
}
build
方法首先遍历方法注解,确定 HTTP 请求方法、相对 URL、是否有请求体、是否为表单编码或多部分编码等信息。然后遍历参数注解,为每个参数创建对应的 ParameterHandler
对象。最后进行一些合法性检查,确保请求配置的正确性,最终创建并返回 RequestFactory
对象。
4.3 createCallAdapter
方法和 createResponseConverter
方法
4.3.1 createCallAdapter
方法
java
java
private static <T, R> CallAdapter<T, R> createCallAdapter(Retrofit retrofit, Method method, Type returnType) {
Annotation[] annotations = method.getAnnotations();
try {
// 遍历调用适配器工厂列表,查找合适的 CallAdapter 工厂
for (CallAdapter.Factory factory : retrofit.callAdapterFactories()) {
CallAdapter<?, ?> adapter = factory.get(returnType, annotations, retrofit);
if (adapter != null) {
// 找到合适的 CallAdapter 工厂,返回其创建的 CallAdapter 对象
return (CallAdapter<T, R>) adapter;
}
}
} catch (RuntimeException e) {
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
throw methodError(method, "Could not locate call adapter for %s.", returnType);
}
createCallAdapter
方法会遍历 retrofit
中的 callAdapterFactories
列表,依次调用每个工厂的 get
方法,传入方法的返回类型、注解和 retrofit
实例,尝试找到一个能够处理该返回类型的 CallAdapter
工厂。如果找到,则返回该工厂创建的 CallAdapter
对象;如果遍历完所有工厂都没有找到合适的,则抛出异常。
4.3.2 createResponseConverter
方法
java
java
private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
// 遍历转换器工厂列表,查找合适的 Converter 工厂
for (Converter.Factory factory : retrofit.converterFactories()) {
Converter<ResponseBody, ?> converter = factory.responseBodyConverter(responseType, annotations, retrofit);
if (converter != null) {
// 找到合适的 Converter 工厂,返回其创建的 Converter 对象
return (Converter<ResponseBody, T>) converter;
}
}
} catch (RuntimeException e) {
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
throw methodError(method, "Could not locate response converter for %s.", responseType);
}
createResponseConverter
方法与 createCallAdapter
方法类似,它会遍历 retrofit
中的 converterFactories
列表,依次调用每个工厂的 responseBodyConverter
方法,传入响应类型、注解和 retrofit
实例,尝试找到一个能够处理该响应类型的 Converter
工厂。如果找到,则返回该工厂创建的 Converter
对象;如果遍历完所有工厂都没有找到合适的,则抛出异常。
五、接口方法调用与 OkHttpCall
5.1 InvocationHandler.invoke
方法回顾
java
java
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 如果调用的是 Object 类的方法,直接调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// 如果是默认方法,根据平台进行处理
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 创建 ServiceMethod 对象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 创建 OkHttpCall 对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 通过 CallAdapter 进行适配
return serviceMethod.callAdapter.adapt(okHttpCall);
}
当调用接口方法时,会触发 InvocationHandler
的 invoke
方法。该方法会先判断调用的是否为 Object
类的方法或接口的默认方法,如果是则直接处理。否则,会加载 ServiceMethod
对象,使用该对象和方法参数创建 OkHttpCall
对象,最后通过 CallAdapter
对 OkHttpCall
对象进行适配并返回适配后的对象。
5.2 OkHttpCall
类
5.2.1 类的基本结构和成员变量
java
java
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final Object[] args;
private volatile boolean canceled;
private @Nullable okhttp3.Call rawCall;
private @Nullable Throwable creationFailure;
private boolean executed;
OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
// ...其他方法
}
OkHttpCall
类实现了 Call
接口,封装了 ServiceMethod
和方法参数。rawCall
是 OkHttp 的 Call
对象,用于实际执行 HTTP 请求。executed
标志该请求是否已经执行过,canceled
标志请求是否被取消。
5.2.2 request
方法
java
java
@Override
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 {
// 创建 OkHttp 的 Request 对象
rawCall = call = serviceMethod.toCall(args);
return call.request();
} catch (RuntimeException | Error e) {
creationFailure = e;
throw e;
}
}
request
方法用于获取实际的 OkHttp 请求对象。如果 rawCall
已经创建,则直接返回其请求对象。如果创建请求时出现异常,会抛出相应的异常。否则,调用 serviceMethod.toCall(args)
方法创建 rawCall
并返回其请求对象。
5.2.3 enqueue
方法
java
java
@Override
public void enqueue(final Callback<T> callback) {
checkNotNull(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 {
// 创建 OkHttp 的 Call 对象
rawCall = call = serviceMethod.toCall(args);
} 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 onFailure(okhttp3.Call call, IOException e) {
// 切换到主线程回调失败结果
callbackOnMain(e);
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 解析响应结果
response = parseResponse(rawResponse);
} catch (Throwable e) {
// 处理解析响应时的异常
callbackOnMain(e);
return;
}
// 切换到主线程回调成功结果
callbackOnMain(response);
}
});
}
// 切换到主线程回调的辅助方法
private void callbackOnMain(final Throwable t) {
// 获取主线程的执行器
executorService.execute(new Runnable() {
@Override
public void run() {
callback.onFailure(OkHttpCall.this, t);
}
});
}
private void callbackOnMain(final Response<T> response) {
executorService.execute(new Runnable() {
@Override
public void run() {
if (response.isSuccessful()) {
callback.onResponse(OkHttpCall.this, response);
} else {
callback.onFailure(OkHttpCall.this, new IOException("HTTP " + response.code()));
}
}
});
}
enqueue
方法用于异步执行请求。首先进行同步控制,确保请求只执行一次。然后创建 rawCall
对象,如果创建过程中出现异常,直接回调失败结果。接着判断请求是否被取消,若取消则取消 rawCall
。最后使用 rawCall
的 enqueue
方法异步执行请求,并在回调中处理响应结果。callbackOnMain
方法用于将回调切换到主线程。
5.2.4 parseResponse
方法
java
java
private Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// 解析响应头
Headers headers = Headers.of(rawResponse.headers());
if (!rawResponse.isSuccessful()) {
// 处理非成功响应
rawBody.close();
return Response.error(parseErrorBodyIfPossible(rawResponse), headers);
}
if (rawBody == null) {
// 处理空响应体
return Response.success(null, headers);
}
// 解析响应体
T body = serviceMethod.toResponse(rawBody);
return Response.success(body, headers);
}
// 解析错误响应体
private IOException parseErrorBodyIfPossible(okhttp3.Response rawResponse) {
try {
return serviceMethod.parseError(rawResponse);
} catch (RuntimeException e) {
return e;
} catch (IOException e) {
return e;
} catch (Throwable t) {
return new RuntimeException(t);
}
}
parseResponse
方法用于解析 OkHttp 的响应结果。如果响应状态码不是 2xx,会处理错误响应。如果响应体为空,返回成功但 body
为 null
的响应。否则,调用 serviceMethod.toResponse(rawBody)
方法解析响应体并返回成功响应。
5.3 ServiceMethod.toCall
方法
java
java
okhttp3.Call toCall(Object... args) {
// 创建 OkHttp 的 Request 对象
Request request = requestFactory.create(args);
// 使用 OkHttp 的 Call.Factory 创建 Call 对象
return callFactory.newCall(request);
}
toCall
方法调用 requestFactory.create(args)
方法创建 OkHttp 的 Request
对象,然后使用 callFactory
创建 Call
对象,用于实际执行 HTTP 请求。
5.4 RequestFactory.create
方法
java
java
Request create(Object... args) {
// 解析请求 URL
HttpUrl baseUrl = this.baseUrl;
String relativeUrl = this.relativeUrl;
HttpUrl.Builder urlBuilder = baseUrl.newBuilder(relativeUrl);
if (urlBuilder == null) {
throw new IllegalArgumentException("Malformed URL.");
}
// 解析请求参数
ParameterHandler<?>[] parameterHandlers = this.parameterHandlers;
Headers.Builder headersBuilder = new Headers.Builder();
RequestBody body = null;
for (int i = 0; i < parameterHandlers.length; i++) {
parameterHandlers[i].apply(args[i], urlBuilder, headersBuilder, bodyBuilder);
}
// 创建 OkHttp 的 Request 对象
return new Request.Builder()
.url(urlBuilder.build())
.headers(headersBuilder.build())
.method(httpMethod, bodyBuilder.build())
.build();
}
create
方法根据 baseUrl
和 relativeUrl
构建请求 URL。然后遍历 parameterHandlers
数组,将方法参数应用到请求的 URL、请求头和请求体中。最后使用 Request.Builder
创建 OkHttp 的 Request
对象。
六、CallAdapter 的适配过程
6.1 CallAdapter
接口和工厂类
java
java
public interface CallAdapter<R, T> {
// 获取响应类型
Type responseType();
// 适配 Call 对象
T adapt(Call<R> call);
// 工厂类,用于创建 CallAdapter 对象
abstract class Factory {
// 根据返回类型和注解创建 CallAdapter 对象
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);
}
}
}
CallAdapter
接口定义了两个方法,responseType
用于获取响应类型,adapt
用于适配 Call
对象。Factory
是一个抽象类,用于创建 CallAdapter
对象。
6.2 ExecutorCallAdapterFactory
和 ExecutorCallAdapter
java
java
public final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
public ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new ExecutorCallAdapter<>(callbackExecutor, responseType);
}
}
final class ExecutorCallAdapter<T, R> implements CallAdapter<T, R> {
private final Executor callbackExecutor;
private final Type responseType;
ExecutorCallAdapter(Executor callbackExecutor, Type responseType) {
this.callbackExecutor = callbackExecutor;
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public R adapt(Call<T> call) {
// 创建适配后的 Call 对象
return (R) new ExecutorCallbackCall<>(callbackExecutor, call);
}
}
final class ExecutorCallbackCall<T> implements Call<T> {
private final Executor callbackExecutor;
private final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
// 检查回调是否为 null
checkNotNull(callback, "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()) {
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);
}
});
}
});
}
// 其他方法直接委托给原始 Call 对象
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override
public Request request() {
return delegate.request();
}
}
ExecutorCallAdapterFactory
是默认的 CallAdapter
工厂类,它会根据返回类型判断是否为 Call
类型,如果是则创建 ExecutorCallAdapter
对象。ExecutorCallAdapter
的 adapt
方法会创建 ExecutorCallbackCall
对象,该对象会将回调切换到指定的线程。
七、Converter 的转换过程
7.1 Converter
接口和工厂类
java
java
public interface Converter<F, T> {
// 转换方法
T convert(F value) throws IOException;
// 工厂类,用于创建 Converter 对象
abstract class Factory {
// 创建请求体转换器
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
// 创建响应体转换器
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
// 创建字符串转换器
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
}
}
Converter
接口定义了 convert
方法,用于进行数据转换。Factory
是一个抽象类,提供了创建请求体转换器、响应体转换器和字符串转换器的方法。
7.2 GsonConverterFactory
和相关转换器
java
java
public final class GsonConverterFactory extends Converter.Factory {
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
@Override
public Converter<ResponseBody, ?> responseBody
7.2 GsonConverterFactory
和相关转换器
java
java
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new GsonResponseBodyConverter<>(gson, type);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return new GsonRequestBodyConverter<>(gson, type);
}
}
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, Type type) {
this.gson = gson;
// 通过 Gson 获取指定类型的 TypeAdapter,用于解析 JSON 数据
this.adapter = gson.getAdapter(TypeToken.get(type));
}
@Override
public T convert(ResponseBody value) throws IOException {
// 创建 JsonReader 对象,用于读取响应体的字符流
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
// 使用 TypeAdapter 从 JsonReader 中读取数据并转换为指定类型
return adapter.read(jsonReader);
} finally {
// 关闭响应体
value.close();
}
}
}
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, Type type) {
this.gson = gson;
// 通过 Gson 获取指定类型的 TypeAdapter,用于将对象转换为 JSON 数据
this.adapter = gson.getAdapter(TypeToken.get(type));
}
@Override
public RequestBody convert(T value) throws IOException {
// 创建 ByteArrayOutputStream 用于存储序列化后的 JSON 数据
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 创建 JsonWriter 对象,用于将对象以 JSON 格式写入输出流
JsonWriter jsonWriter = gson.newJsonWriter(new OutputStreamWriter(out, UTF_8));
try {
// 使用 TypeAdapter 将对象写入 JsonWriter
adapter.write(jsonWriter, value);
// 刷新 JsonWriter 以确保所有数据都被写入输出流
jsonWriter.close();
} catch (IOException e) {
// 捕获可能的 I/O 异常并重新抛出
throw new AssertionError(e); // Writing to a buffer can't throw an IOException.
}
// 创建 OkHttp 的 RequestBody 对象,指定媒体类型和字节数组
return RequestBody.create(MEDIA_TYPE, out.toByteArray());
}
}
7.2.1 GsonConverterFactory
分析
GsonConverterFactory
是一个实现了 Converter.Factory
接口的工厂类,它的主要作用是创建 Gson
相关的请求体转换器和响应体转换器。通过调用 create
方法可以传入自定义的 Gson
实例,如果不传入则使用默认的 Gson
实例。
7.2.2 GsonResponseBodyConverter
分析
- 构造函数 :接收
Gson
实例和目标类型type
,通过Gson
的getAdapter
方法获取对应的TypeAdapter
,这个TypeAdapter
是Gson
用于序列化和反序列化对象的核心工具。 convert
方法 :将ResponseBody
转换为目标类型T
。首先创建JsonReader
用于读取响应体的字符流,然后使用TypeAdapter
从JsonReader
中读取数据并转换为目标类型,最后关闭响应体。
7.2.3 GsonRequestBodyConverter
分析
- 构造函数 :同样接收
Gson
实例和目标类型type
,获取对应的TypeAdapter
。 convert
方法 :将目标类型T
的对象转换为RequestBody
。创建ByteArrayOutputStream
用于存储序列化后的 JSON 数据,再创建JsonWriter
将对象以 JSON 格式写入输出流,最后使用RequestBody.create
方法创建RequestBody
对象。
7.3 其他常见的 Converter 工厂
7.3.1 ScalarsConverterFactory
java
java
public final class ScalarsConverterFactory extends Converter.Factory {
private static final MediaType MEDIA_TYPE = MediaType.get("text/plain; charset=UTF-8");
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == String.class) {
return new StringResponseBodyConverter();
}
if (type == ByteString.class) {
return new ByteStringResponseBodyConverter();
}
if (type == byte[].class) {
return new ByteArrayResponseBodyConverter();
}
return null;
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (type == String.class) {
return new StringRequestBodyConverter();
}
if (type == ByteString.class) {
return new ByteStringRequestBodyConverter();
}
if (type == byte[].class) {
return new ByteArrayRequestBodyConverter();
}
return null;
}
static final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
@Override
public String convert(ResponseBody value) throws IOException {
try {
return value.string();
} finally {
value.close();
}
}
}
static final class ByteStringResponseBodyConverter implements Converter<ResponseBody, ByteString> {
@Override
public ByteString convert(ResponseBody value) throws IOException {
try {
return value.source().readByteString();
} finally {
value.close();
}
}
}
static final class ByteArrayResponseBodyConverter implements Converter<ResponseBody, byte[]> {
@Override
public byte[] convert(ResponseBody value) throws IOException {
try {
return value.bytes();
} finally {
value.close();
}
}
}
static final class StringRequestBodyConverter implements Converter<String, RequestBody> {
@Override
public RequestBody convert(String value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
}
static final class ByteStringRequestBodyConverter implements Converter<ByteString, RequestBody> {
@Override
public RequestBody convert(ByteString value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
}
static final class ByteArrayRequestBodyConverter implements Converter<byte[], RequestBody> {
@Override
public RequestBody convert(byte[] value) throws IOException {
return RequestBody.create(MEDIA_TYPE, value);
}
}
}
- 功能概述 :
ScalarsConverterFactory
用于处理基本数据类型(如String
、ByteString
、byte[]
)的转换。它提供了响应体转换器和请求体转换器,分别用于将响应体转换为基本数据类型和将基本数据类型转换为请求体。 - 响应体转换器 :根据目标类型的不同,分别创建
StringResponseBodyConverter
、ByteStringResponseBodyConverter
或ByteArrayResponseBodyConverter
,通过ResponseBody
的相应方法读取数据并转换为目标类型。 - 请求体转换器 :根据源类型的不同,分别创建
StringRequestBodyConverter
、ByteStringRequestBodyConverter
或ByteArrayRequestBodyConverter
,使用RequestBody.create
方法将数据转换为RequestBody
。
7.3.2 MoshiConverterFactory
java
java
public final class MoshiConverterFactory extends Converter.Factory {
private final Moshi moshi;
private final boolean lenient;
private final boolean failOnUnknown;
private final boolean serializeNulls;
public static MoshiConverterFactory create() {
return create(new Moshi.Builder().build());
}
public static MoshiConverterFactory create(Moshi moshi) {
return new MoshiConverterFactory(moshi, false, false, false);
}
private MoshiConverterFactory(Moshi moshi, boolean lenient, boolean failOnUnknown, boolean serializeNulls) {
this.moshi = moshi;
this.lenient = lenient;
this.failOnUnknown = failOnUnknown;
this.serializeNulls = serializeNulls;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
JsonAdapter<?> adapter = moshi.adapter(type);
if (lenient) {
adapter = adapter.lenient();
}
if (failOnUnknown) {
adapter = adapter.failOnUnknown();
}
if (serializeNulls) {
adapter = adapter.serializeNulls();
}
return new MoshiResponseBodyConverter<>(adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
JsonAdapter<?> adapter = moshi.adapter(type);
if (lenient) {
adapter = adapter.lenient();
}
if (failOnUnknown) {
adapter = adapter.failOnUnknown();
}
if (serializeNulls) {
adapter = adapter.serializeNulls();
}
return new MoshiRequestBodyConverter<>(adapter);
}
}
final class MoshiResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final JsonAdapter<T> adapter;
MoshiResponseBodyConverter(JsonAdapter<T> adapter) {
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
try {
return adapter.fromJson(value.source());
} finally {
value.close();
}
}
}
final class MoshiRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private final JsonAdapter<T> adapter;
MoshiRequestBodyConverter(JsonAdapter<T> adapter) {
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
adapter.toJson(buffer, value);
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
- 功能概述 :
MoshiConverterFactory
是基于Moshi
库的转换器工厂,用于处理 JSON 数据的序列化和反序列化。Moshi
是一个轻量级的 JSON 解析库,性能较好。 - 响应体转换器 :
MoshiResponseBodyConverter
通过JsonAdapter
的fromJson
方法将ResponseBody
中的 JSON 数据转换为目标类型。 - 请求体转换器 :
MoshiRequestBodyConverter
通过JsonAdapter
的toJson
方法将目标类型的对象转换为 JSON 数据,并创建RequestBody
对象。
八、请求拦截器和网络层处理
8.1 请求拦截器
在 Retrofit 中,可以通过 OkHttp 的拦截器对请求和响应进行拦截处理。以下是一个简单的请求拦截器示例:
java
java
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class CustomInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
// 获取原始请求
Request originalRequest = chain.request();
// 可以对请求进行修改,例如添加请求头
Request newRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer your_token")
.build();
// 继续执行请求
return chain.proceed(newRequest);
}
}
在创建 OkHttpClient
时添加该拦截器:
java
java
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new CustomInterceptor())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(client)
.build();
8.1.1 拦截器原理
Interceptor
接口定义了一个intercept
方法,该方法接收一个Chain
对象。Chain
对象包含了原始请求和处理请求的上下文信息。- 在
intercept
方法中,可以对原始请求进行修改,例如添加请求头、修改请求参数等。 - 调用
chain.proceed(newRequest)
方法继续执行修改后的请求,并返回响应。
8.2 网络层处理
Retrofit 底层使用 OkHttp 进行网络请求,OkHttp 提供了强大的网络层处理能力,包括连接池管理、缓存、重试机制等。
8.2.1 连接池管理
java
java
OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))
.build();
上述代码创建了一个连接池,最多允许 5 个空闲连接,每个连接的空闲时间最长为 5 分钟。连接池的作用是复用已经建立的连接,减少连接建立和关闭的开销,提高网络请求的性能。
8.2.2 缓存机制
java
java
File cacheDirectory = new File(context.getCacheDir(), "http_cache");
Cache cache = new Cache(cacheDirectory, 10 * 1024 * 1024); // 10 MB
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
上述代码创建了一个缓存目录和一个大小为 10 MB 的缓存对象,并将其添加到 OkHttpClient
中。OkHttp 会根据响应头的 Cache-Control
和 Expires
字段来判断是否可以使用缓存,从而减少不必要的网络请求。
8.2.3 重试机制
OkHttp 本身没有提供内置的重试机制,但可以通过自定义拦截器来实现。以下是一个简单的重试拦截器示例:
java
java
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class RetryInterceptor implements Interceptor {
private static final int MAX_RETRIES = 3;
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = null;
IOException exception = null;
for (int i = 0; i < MAX_RETRIES; i++) {
try {
response = chain.proceed(request);
if (response.isSuccessful()) {
return response;
}
} catch (IOException e) {
exception = e;
}
}
if (exception != null) {
throw exception;
}
return response;
}
}
在创建 OkHttpClient
时添加该拦截器:
java
java
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new RetryInterceptor())
.build();
该重试拦截器会在请求失败时最多重试 3 次,直到请求成功或达到最大重试次数。
九、错误处理和异常情况
9.1 网络请求错误处理
在使用 Retrofit 进行网络请求时,可能会遇到各种错误,例如网络连接失败、服务器返回错误状态码等。以下是处理这些错误的常见方式:
9.1.1 异步请求错误处理
java
java
Call<MyResponse> call = service.getMyData();
call.enqueue(new Callback<MyResponse>() {
@Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if (response.isSuccessful()) {
MyResponse data = response.body();
// 处理成功响应
} else {
try {
// 获取错误响应体
String errorBody = response.errorBody().string();
// 处理错误响应
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<MyResponse> call, Throwable t) {
// 处理请求失败,例如网络连接失败
t.printStackTrace();
}
});
在 onResponse
方法中,通过 response.isSuccessful()
判断响应是否成功,如果失败则可以通过 response.errorBody()
获取错误响应体。在 onFailure
方法中,处理请求失败的情况,例如网络连接失败、请求超时等。
9.1.2 同步请求错误处理
java
java
try {
Call<MyResponse> call = service.getMyData();
Response<MyResponse> response = call.execute();
if (response.isSuccessful()) {
MyResponse data = response.body();
// 处理成功响应
} else {
try {
// 获取错误响应体
String errorBody = response.errorBody().string();
// 处理错误响应
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
// 处理请求失败,例如网络连接失败
e.printStackTrace();
}
同步请求通过 try-catch
块捕获可能的 IOException
异常,在异常处理中可以处理网络连接失败等情况。
9.2 异常情况分析
9.2.1 注解使用错误
如果在 API 接口方法中使用注解不当,例如使用了不兼容的注解组合或注解参数错误,会在创建 ServiceMethod
或 RequestFactory
时抛出异常。例如:
java
java
@GET("users/{user}")
@POST("users/{user}") // 错误:一个方法不能同时使用 @GET 和 @POST 注解
Call<ResponseBody> getUser(@Path("user") String user);
这种情况下,RequestFactory
的 build
方法会抛出异常,提示只能使用一个 HTTP 方法注解。
9.2.2 类型转换异常
如果使用的 Converter
无法处理请求参数或响应结果的类型,会抛出类型转换异常。例如,使用 GsonConverterFactory
处理非 JSON 格式的数据,或者使用 ScalarsConverterFactory
处理复杂的对象类型。
9.2.3 网络连接异常
在网络请求过程中,可能会遇到网络连接失败、请求超时等异常。这些异常通常会在 OkHttpCall
的 enqueue
或 execute
方法中抛出,并通过 Callback
的 onFailure
方法回调给调用者。
十、总结与展望
10.1 总结
通过对 Retrofit 请求执行模块的深入源码分析,我们了解了 Retrofit 的核心工作原理。从 Retrofit 实例的创建、接口代理对象的生成,到请求的执行、响应的处理,每个环节都有其独特的设计和实现。
- 模块化设计 :Retrofit 采用了高度模块化的设计,将不同的功能拆分成多个模块,如
CallAdapter
、Converter
、Interceptor
等。这种设计使得 Retrofit 具有很强的扩展性,开发者可以根据自己的需求替换或扩展这些模块。 - 注解驱动:使用注解来定义 API 接口方法的请求信息,使得代码简洁、易读且易于维护。注解的使用也提高了代码的灵活性,开发者可以根据不同的需求选择不同的注解组合。
- 与 OkHttp 集成:Retrofit 底层使用 OkHttp 进行网络请求,借助 OkHttp 的强大功能,如连接池管理、缓存、拦截器等,提高了网络请求的性能和稳定性。
10.2 展望
随着技术的不断发展,Retrofit 也可以在以下方面进行改进和拓展:
10.2.1 支持新的网络协议
随着 HTTP/3 等新的网络协议的逐渐普及,Retrofit 可以考虑支持这些新协议,以进一步提高网络请求的性能和安全性。
10.2.2 更好的异步编程支持
虽然 Retrofit 已经支持异步请求,但可以进一步优化对 Kotlin 协程、Java 异步流等异步编程模型的支持,使开发者能够更方便地进行异步编程。
10.2.3 增强错误处理和调试功能
可以提供更详细的错误信息和调试工具,帮助开发者更快地定位和解决问题。例如,在异常信息中提供更多的上下文信息,或者提供可视化的调试工具。
10.2.4 跨平台支持
除了 Android 和 Java 平台,Retrofit 可以考虑提供对其他平台的支持,如 iOS、Web 等,以扩大其应用范围。
综上所述,Retrofit 是一个优秀的网络请求框架,通过深入理解其源码和工作原理,开发者可以更好地使用和扩展该框架,提高开发效率和应用性能。