Retrofit 源码分析
知识预热
JAVA泛型类型
type | description | example | remark |
---|---|---|---|
ParameterizedType | 参数化类型,通常意义上的泛型类型类实例 | List,Map<K,V> | |
TypeVariable | 类型化变量 泛型变量 | T t,K k,V v | |
GenericArrayType | 泛型数组 | List[], T[], | |
WildcardType | 通配符类型 | List<? extends String> | |
Class | 字节码类型 |
JDK动态代理
动态代理
是AOP
(面向切面编程)的重要组成部分。
JDK动态动态代理
要求被代理对象必须实现接口,InvocationHandler
的派生类通过聚合该接口的实例,在其invoke
方法中,转发接口的调用。示例如下,我们需要在某个代理对象的方法前后打印输入。
假设存在某一服务接口如下
public interface IServer {
void sayHello();
}
业务类实现了该接口
public class Engine implements IServer {
@Override
public void sayHello() {
System.out.println("Hello,I am Agent");
}
}
现在通过动态代理在方法前后打印输出。先定义自定义InvocationHandler
class ICommonHandler implements InvocationHandler {
// 这里持有了IServer接口的实例
private IServer agent;
public ICommonHandler(IServer agent){
this.agent = agent;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
// 调用前,修饰方法
System.out.println("before function invoke");
// 将调用准发给被代理对象
Object result = method.invoke(agent, objects);
// 调用前后修饰方法
System.out.println("after function invoke");
return result;
}
}
最后,通过Proxy.newProxyInstance
API获取代理后的对象。
public static void main(String[] args) {
try {
// 被代理对象
Engine agent = new Engine();
// InvocationHandler
ICommonHandler invocationHandler = new ICommonHandler(agent);
// 获取动态代理后的对象
IServer proxy = (IServer) Proxy.newProxyInstance(agent.getClass().getClassLoader(), agent.getClass().getInterfaces(), invocationHandler);
// 通过代理对象调用相应的api
proxy.sayHello();
}catch(Exception exception){
exception.printStackTrace();
}
}
JAVA反射相关
- Method.getAnnotations:获取方法上的注解
- Method.getGenericParameterTypes:获取方法参数类型
- Method.getParameterAnnotations:获取方法参数注解
// 为了理解上述API,举例如下
// 自定义一个注解
@Retention(AnnotationRetention.RUNTIME)
annotation class JSON{
}
// 假设有如下接口类
interface GitHubService {
@GET("users/{user}/repos")
@HEAD(value = "contentType:application/json")
fun listRepos(@Path("user")user:String,@JSON @Query("sign")sign:String): Call<List<Repo>>
}
// 测试类
public class Reflex {
public static void main(String[] args) {
try {
Class<GitHubService> clazz = GitHubService.class;
Method[] methods = clazz.getMethods();
for(Method method:methods){
method.setAccessible(true);
System.out.println("method:"+method.getName()+"*************************");
Annotation[] annotations = method.getAnnotations();
Type[] genericParameterTypes = method.getGenericParameterTypes();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for(Annotation annotation:annotations){
System.out.println("annotation:"+annotation.toString());
}
System.out.println("----------------------------------------");
for(Type type:genericParameterTypes){
System.out.println("types:"+type.getTypeName());
}
System.out.println("----------------------------------------");
for(Annotation[] a1:parameterAnnotations){
for(Annotation a:a1){
System.out.println("parameterAnnotation:"+a.toString());
}
System.out.println("##########################################");
}
System.out.println("----------------------------------------");
System.out.println("method:"+method.getName()+"*************************");
}
}catch(Exception exception){
exception.printStackTrace();
}
}
}
打印如下
method:listRepos*************************
# getAnnotations
annotation:@retrofit2.http.GET(value=users/{user}/repos)
annotation:@retrofit2.http.HEAD(value=contentType:application/json)
----------------------------------------
# getGenericParameterTypes
types:java.lang.String
types:java.lang.String
----------------------------------------
# getParameterAnnotations
parameterAnnotation:@retrofit2.http.Path(encoded=false, value=user)
##########################################
parameterAnnotation:@api.JSON()
parameterAnnotation:@retrofit2.http.Query(encoded=false, value=sign)
##########################################
----------------------------------------
method:listRepos*************************
Retrofit使用
在module
的build.gradle.kts
文件中添加如下依赖
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0")
}
创建API
接口
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
通过Retrofit
实例生成实现API
接口的实例对象
// 获取Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
通过该对象可以实现真实的HTTP
访问
Call<List<Repo>> repos = service.listRepos("alibaba");
源码分析
在Retrofit
的使用过程中,Retrofit
类通过构建者
模式生成了一个Retrofit
的实例,该实例通过create
方法生成实现API
接口的对象。create
方法返回一个实现API
接口的对象,其源码如下:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
// 验证API接口的有效性
validateServiceInterface(service);
// 这里直接使用了java的动态代理
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
方法的核心是通过动态代理技术,返回一个代理实例.在返回代理对象之前,必须对传入的API
接口进行校验.
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());
}
if (validateEagerly) {
// 平台类型工具类
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
// 加载所有的非默认方法与非静态方法(jdk1.8在接口了增加了default方法的定义)
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
接口验证的主要目的在于确定API
接口是纯粹的接口
,首先从语义上必须是一个Interface
,其次,必须是一个非泛型接口,最后,通过loadServiceMehod
方法加载接口中所有的非默认方法与非静态方法.
ServiceMethod<?> loadServiceMethod(Method method) {
// serviceMethodCache 是一个类型安全的容器,通过缓存,保证方法的解析只进行一次
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 同步代码
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 解析方法,并返回ServiceMehod对象
result = ServiceMethod.parseAnnotations(this, method);
// 将解析结果存放在缓存中,避免下次再次解析方法
serviceMethodCache.put(method, result);
}
}
return result;
}
loadServiceMehod
方法通过ServiceMethod.parseannotations
的静态方法解析接口中的方法,并返回一个ServiceMethod
对象,当用户调用接口中的方法时,其实最终调用的是serviceMethod.invoke
函数.需要说明的一点是,用户存在多次调用接口中的同一方法,为了避免每次调用都解析方法一次,loadServiceMehod
方法在解析方法过程中使用了内存缓存,即通过ConcurrentHashMap
这样一个线程安全的容器去缓存每次解析的结果.
ServiceMethod
的类定义
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> 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.");
}
// 这里主要是加入了对kotlin协程的支持,继续解析方法返回值
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
// 外部调用API服务最终通过该方法
abstract @Nullable T invoke(Object[] args);
}
方法注解的解析
parseAnnotations()
方法主要用于解析方法注解,并返回RequestFactory
对象.该方法的主要逻辑如上注解所有.需要说明的是最新版本的Retrofit
已经支持Kotlin 协程
,所以在最新的源码中,可以看见这部分的源码.
个人感觉Retrofit
在解析方法注解这部分做的非常优雅.parseAnnotations
方法如下
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
// RequestFactory 使用了构建者模式.
return new Builder(retrofit, method).build();
}
}
他的构建者如下,在其构造方法参数中,methodAnnotations
,parameterTypes
,parameterAnnotationsArray
这三个参数非常重要,因为后续的所有解析操作均围绕这三者,在构建者的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() {
for (Annotation annotation : methodAnnotations) {
// 解析方法注解
parseMethodAnnotation(annotation);
}
// 解析方法后验证相关参数
// 如接口中必须表明HTTP的连接方式 GET,POST,PUT,PATCH,DELETE等
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 如果存在请求体,则不能以表单方式传参
if (!hasBody) {
if (isMultipart) {
throw methodError(
method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(
method,
"FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
// 解析方法参数部分
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);
}
// 解析后再次验证相关参数
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
// 返回RequestFactory对象
return new RequestFactory(this);
}
解析的过程比较简单
-
先解析方法参数
-
再解析方法
##### `解析方法上的注解`
在上述的方法中,通过parseMethodAnnotation
方法解析方法上的注解
// 解析方法注解
// 通过枚举不同的注解类型,可以判断如下信息
// 1.HTTP请求方法,delete,post,get,put,patch,options,delete
// 2.通过请求方式,确认是否存在请求体
// 3.通过请求方式,确认参数组织方式,请求体或者表单传参
// 4.通过注解中参数,可以确定HTTP的路径,相对于BaseUrl
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);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} 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 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;
}
}
上述的业务逻辑比较简单,通过方法注解可以了解如下的基本信息
-
HTTP请求方法,delete,post,get,put,patch,options,delete
-
通过请求方式,确认是否存在请求体,只有
post
,put
,patch
方式的请求才可能携带请求体 -
通过
@FormUrlEncoded
与Multipart
注解确认是否通过表单传参 -
通过注解参数确认相对路径
-
通过
Heads
与Head
注解确认请求头
解析方法参数
当方法注解解析完成后,需要对部分解析结果做验证,验证的方向为请求体与表单传参两者不可同时存在.验证之后即可以开始解析方法参数.在源码中通过如下代码实现
// parameterAnnotationsArray 为方法参数中的注解数组
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
// 每一个参数的解析结果都返回一个parameterHandler的结果
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
方法参数的注解最终调用的函数为parseParameter
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != 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;
}
}
// 适配kotlin协程
if (result == null) {
// 确认是supend函数的依据为最后方法参数为Continuation类型(续体)
if (allowContinuation) {
try {
// 确认是kotlin suspend 函数
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
在上述方法中,parseParameterAnnotation
为最终调用的解析方法参数的方法,该方法比较长,他会枚举所有的注解类型,针对不同类型使用不同解析策略,并返回统一的解析结果ParameterHandler
,部分源码如下
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) {
validateResolvableType(p, type);
//
// 参数验证.....
//
gotUrl = true;
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
return new ParameterHandler.RelativeUrl(method, p);
} else {
throw parameterError(
method,
p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}
}else if(annotation instanceof Path){
validateResolvableType(p, type);
//
// 参数验证.....
//
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
}else if(annotation instanceof Query){
// ....
}
// ...
}
在上述方法中,针对不同的注解类型提供了不同的解析策略,解析的结果对象为ParameterHandler
.
abstract class ParameterHandler<T> {
abstract void apply(RequestBuilder builder, @Nullable T value) throws IOException;
final ParameterHandler<Iterable<T>> iterable() {
return new ParameterHandler<Iterable<T>>() {
@Override
void apply(RequestBuilder builder, @Nullable Iterable<T> values) throws IOException {
if (values == null) return; // Skip null values.
for (T value : values) {
ParameterHandler.this.apply(builder, value);
}
}
};
}
final ParameterHandler<Object> array() {
return new ParameterHandler<Object>() {
@Override
void apply(RequestBuilder builder, @Nullable Object values) throws IOException {
if (values == null) return; // Skip null values.
for (int i = 0, size = Array.getLength(values); i < size; i++) {
//noinspection unchecked
ParameterHandler.this.apply(builder, (T) Array.get(values, i));
}
}
};
}
}
这是一个抽象类,针对不同的注解,他提供了非常多的实现类
// Url注解的策略解析
static final class RelativeUrl extends ParameterHandler<Object> {
private final Method method;
private final int p;
RelativeUrl(Method method, int p) {
this.method = method;
this.p = p;
}
@Override
void apply(RequestBuilder builder, @Nullable Object value) {
if (value == null) {
throw Utils.parameterError(method, p, "@Url parameter is null.");
}
builder.setRelativeUrl(value);
}
}
// Heads/Head注解的策略解析
static final class Header<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
Header(String name, Converter<T, String> valueConverter) {
this.name = Objects.requireNonNull(name, "name == null");
this.valueConverter = valueConverter;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
String headerValue = valueConverter.convert(value);
if (headerValue == null) return; // Skip converted but null values.
builder.addHeader(name, headerValue);
}
}
最终,解析完方法参数后,所有的结果存储在RequestFactory.parameterHandlers
属性中,最终在构建Request
过程中会通过ParameterHandler
的apply
方法,逐步的完善Request
,最终组成完整的Request
.但此已是后话
函数返回值的解析
Retrofit
已经支持Kotlin
的协程
.在解析方法注解以及参数的过程中已经有体现.接下来,在解析方法返回值中也同样体现.在ServiceMethod
类中,
static <T> ServiceMethod<T> 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);
}
HttpServiceMethod.parseAnnotations
方法如下
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
/**
* Inspects the annotations on an interface method to construct a reusable service method that
* speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
* method only once and reuse it.
*/
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 在上面的"RequestFactory.parseAnnotations"方法已经确定是否为susppend函数
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
// susspend 函数类型
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
// Response<T>类型
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
// 后续通过adapterType确认CallAdapter类型 Call<T>
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
// 获取CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(
method,
"'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 获取Convert
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
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);
}
}
}
HttpServiceMethod
是一个抽象类,分别有三个静态内部的实现类CallAdapted
,SuspendForResponse
,SuspendForBody
.在其parseAnnotations
方法中,最终会返回上述三个实现类其中的一个.上述三个静态实现类的构造函数参数非常重要,举其中一简单的实现类
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
// 在ServiceMethod父类中完成构造完成
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
// 父类createCallAdapter方法
Converter<ResponseBody, ResponseT> responseConverter,
// 父类createResponseConverter方法
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
在上述的构造函数中需要传入三个非常重要的对象RequestFactory
,在对象的创建在ServiceMethod
类中RequestFactory.parseAnnotations(retrofit, method)
.而Convert
与CallAdapter
均在其父类HttpServiceMethod
中构建,具体如下
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 省略其他业务代码
// calladapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// Convert
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
}
追踪上述代码,最终发现,这两者的获取的对象都是retrofit
持有的对象.
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List<Converter.Factory> converterFactories,
List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor,
boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
// convert
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
// calladapter
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
Retrofit
采用构建者模式,build
方法方法中会预先加入一些内建的CallAdapter
与Convert.Factory
实例
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.
// 加入内建的CallAdapter 工厂
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> 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.
// 加入内建的Convert
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
platform.defaultCallAdapterFactories(callbackExecutor)
内建的CallAdapter
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
这些内建的CallAdapter
具体业务逻辑代码都比较简单.但需要知道的是,在Retrofit
调用具体的API
访问过程中最终都会调用到其中的adapter
方法.具体的调用逻辑为
abstract class ServiceMethod<T> {
abstract @Nullable T invoke(Object[] args);
}
到其子类``
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
}
查看HttpserviceMethod
三个静态内部类,其adapter
方法最终都会调用到callAdapter.adapter
方法,也就是Retrofit
内一些列的callAdapter
.查看一下OkhttpCall
的类,发现桥接okhttp
的一些列代码.查看其中比较重要的方法
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
这里通过requestFactory
已经API
传进来的参数,构建了一个Okhttp3.Call
.这里可以看到requestFactory
的最终归宿了.
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse =
rawResponse
.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 这里使用了convert,将requestbody 转化为具体对象
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
需要注意的是parseResponse
方法会在enqueue
方法中调用,而OkHttpCall
会被传递进CallAdapter
,所以CallAdapter
是先于Convert
被调用的.知道了这点,后续在解决很多业务问题可以是少走点弯路.
retrofit
整体调用流程大概如上.