总结源码流程
-
通过Retrofit.create(Class)方法创建出Server interface的实例
-
Retrofit.create(Class)方法内部,使用Proxy.newProxyInstance()方法创建出Server实例。这个方法会为参数中的多个Interface(具体到Retrofit来说,是固定传入一个Interface)创建对象。这个对象实现了所有interface的每一个方法。使用动态代理实现了对象创建,即InvocationHandler.invke()方法。
-
InvocationHandler.invke()方法实现如下:
-
创建ServerMethod
ServerMethod<Object, Object> ServerMethod = (ServerMethod<Object, Object>) loadServerMethod(method);读取interface中方法的所有信息(返回类型,参数,参数注解,反射注解),并初步分析。
-
创建OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(ServerMethod, args);okHttpCall是retrofit2.call的子类,将ServerMethod封装至一个retrofit2.call对象。在enqueue()方法调用的时候用ServerMethod中包含的信息创建出OkHttp3.call对象。并调用发起网络请求。并对结果做预处理
-
adapt()
return ServerMethod.adapt(okHttpCall);会使用ServerMethod中的CallAdapter对象吧OkhttpCall对象进行转换,生成一个新的Retrofit2.Call对象,并且后台线程发起请求,主线程回调处理结果,完成切换线程的工作。还可以生成Obervable等对象。
-
-
A type-safe HTTP client for Android and Java.
Retrofit源码结构不算很复杂,此次解析的Retrofit版本为2.9.0。
2.9.0版本和老版的Retrofit的概念模型差距不大,但是对整体结构变化较大。
本文预计游览时间16分钟,建议使用Night主题查看
基本使用
解析实例先引用最简单的Call实现为例子。
- Retrofit创建
val retrofit = Retrofit.Builder()
.baseUrl("https://wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
- interface声明
interface WanAndroidApi {
@GET("article/listproject/{pageindex}/json")
fun getProjectListWithCall(@Path("pageindex") pageindex: Int): Call<BaseModel<ProjectListBean>>
}
- API创建
var wanAndroidApi = retrofit.create(WanAndroidApi::class.java)
- 请求
wanAndroidApi.getProjectListWithCall(0)
.enqueue(object : Callback<BaseModel<ProjectListBean>> {
override fun onFailure(call: Call<BaseModel<ProjectListBean>>, t: Throwable) {
Timber.i(t)
}
override fun onResponse(
call: Call<BaseModel<ProjectListBean>>,
response: Response<BaseModel<ProjectListBean>>
) {
Timber.i(response.toString())
}
})
首先按照程序入口,我们分析下retrofit的创建过程
Retrofit.Builder()
Platform
Platform.get()
- 首先会在Builder的构造里调用Platform.get()的方法,追踪代码,最后执行到findPlatform()方法。findPlatform()方法会根据虚拟机平台去具体平台,代码如下。
public Builder() {
this(Platform.get());
}
static Platform get() {
return PLATFORM;
}
private static final Platform PLATFORM = findPlatform();
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android() //
: new Platform(true);
}
- Platform构造的hasJava8Types参数用于区分是否支持java8平台,如果是java8平台,Retrofit通过MethodHandle去检测是否有私有接口,并且通过反射开启访问限制。
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
Constructor<Lookup> lookupConstructor = null;
if (hasJava8Types) {
try {
lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
lookupConstructor.setAccessible(true);
} catch (NoClassDefFoundError ignored) {
} catch (NoSuchMethodException ignored) {
}
}
this.lookupConstructor = lookupConstructor;
}
另外还做了异常处理
1.虑到了Android API 24 或者 25下,Lookup.class是不存在的,捕捉了NoClassDefFoundError 2.在JDK 14以下是没有getDeclaredConstructor方法的,捕获了NoSuchMethodException
- Android是继承Platform的实现,构造通过SDK版本判断,如果大于23会开启JAVA8支持。并且重写了defaultCallbackExecutor()方法,提供了MainThreadExecutor。其内部会获取MainLooper构建handler,execute方法直接handler.post(runnable),实现在主线程上的操作。
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Nullable
@Override
Object invokeDefaultMethod(
Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
if (Build.VERSION.SDK_INT < 26) {
throw new UnsupportedOperationException(
"Calling default methods on API 24 and 25 is not supported");
}
return super.invokeDefaultMethod(method, declaringClass, object, args);
}
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
- 除了介绍Platform的获取,还有一些关键方法。
defaultCallAdapterFactories()
这个方法是提供了默认的CallAdapter,所以在初始化Retrofit时不调用addCallAdapterFactory()方法也有默认实现。
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
- 通过hasJava8Types区分java平台,如果不是JAVA8平台就会只添加一个DefaultCallAdapterFactory。如果是的话还会多添加一个CompletableFutureCallAdapterFactory。为了减少代码理解复杂程度,我们先只看DefaultCallAdapterFactory的实现,CompletableFutureCallAdapterFactory下文会详细介绍。
CompletableFutureCallAdapterFactory其实是对CompletableFuture进行了适配。CompletableFuture提供了异步函数式编程,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法
defaultConverterFactories()
这个方法依然是根据hasJava8Types区分返回OptionalConverterFactory还是emptyList。
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
}
Builder()
- 现在回到最初的.Builder()方法,我们看一下完整实现。除了Platform的赋值,还实现了以下属性。
| 变量 | 说明 |
|---|---|
| baseUrl | 默认地址 |
| callFactory:okhttp3.Call.Factory | okhttp默认实现的工厂 |
| callbackExecutor | 默认的请求回调池 |
| validateEagerly | 是否进行激进化验证 |
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
for (int i = 1,size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();i < size;i++) {
converterFactories.add(retrofit.converterFactories.get(i));
}
for (int i = 0,size =retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();i < size;i++) {
callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
}
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
其实这个方法只能通过.build()之后的newBuilder()方法才能调到,Retrofit很巧妙的让开发者在build之后还能再次通过newBuilder()拿到Builder对象,然后通过addCallAdapterFactory一类的方法添加到已有的对象属性里。
build()
- 看完Builder()方法,我们来看下build()方法,其实很简单。
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();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<Converter.Factory> converterFactories =new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
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;
this.converterFactories = converterFactories;
this.callAdapterFactories = callAdapterFactories;
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
实现了如下功能:
- 检查BaseUrl的是否为空,如果为空抛出Base URL required.
- 检查callFactory是否为空,如果为空指定OkHttpClient();
- 检查callbackExecutor是否为空,如果为空指定为platform的默认回调线程池。也就是说如果平台为Android,默认提供MainThreadExecutor()。
- 把platform默认提供的默认的Call对象转换器添加到callAdapterFactories。按照刚才的思路,也就是添加了DefaultCallAdapterFactory的实现。
- 根据之前传入的Converter.Factory的size+platform提供的默认转换器工厂的size+1,创建出converterFactories,为后期的转换提供默认实现。
- 最后把上面说明的属性全部赋值。
最后我们整合下Retrofit.Builder()........build()整体思路,概念模型思路如下(除去细节)
- 首先区分出是Android平台还是java平台,用于初始化默认的defaultCallAdapterFactories和defaultConverterFactories。
- 根据初始化的各个属性,在调用build()时,把各个属性进行赋值
是不是其实很简单。
create()
基于我们分析的基本概念模型,接下来我们从.create()方法入手,分析Retrofit的核心代码。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
validateServiceInterface()
- 首先第一步调用了validateServiceInterface(service)方法,也就是上文分析得出的激进化验证,代码实现如下
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()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
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;
}
代码其实很简单,实现了如下功能:
-
验证传入的service是否是interfaces,不是则抛出API declarations must be interfaces.
-
基于ArrayDeque双向列表实现service的检查管理。检查内容如下:
2.1. 先把service填入到列表check,然后进行while循环检查
2.2. 然后把刚才加入的service删除掉,对次service进行检查
2.3. 检查类型参数的准确性,检查实例是否同步
2.4. 如果检查未通过,则直接抛出异常,如果检查通过,重新添加至列表check
-
如果validateEagerly为true,则进入激进化验证。首先会过滤掉service的默认方法和静态方法。
-
然后执行loadServiceMethod()方法
-
把过滤之后的方法,在同步代码块内部调用ServiceMethod.parseAnnotations(this, method);方法,方法会在内部继续判断过滤,如果通过,则添加到serviceMethodCache之中。serviceMethodCache是ConcurrentHashMap,也就是线程安全的HashMap。能看出Retrofit 的代码十分严谨。
parseAnnotations()
- 分析得出我们需要看ServiceMethod的parseAnnotations方法,此方法很关键,其实调用了parseAnnotations()方法和build()方法,实现如下:
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);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
return new RequestFactory(this);
}
首先看Builder构造,代码如下:
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
很简单,就是Retrofit实例的赋值,方法的赋值,方法注解的赋值,参数类型的赋值,参数注解列表的赋值。
接下里分析build()的内部实现,内部关键方法为parseMethodAnnotation()和parseParameterAnnotation()。除两方法之外还有一些其他预处理。
parseMethodAnnotation()
-
调用parseMethodAnnotation()方法把接口获取的方法注解(methodAnnotations)进行准确性检查。并根据请求方法预处理。处理内容如下:
1.1 会根据httpMethod是否为空判断,限制只有一个Http方法被允许,不能允许多个Http方法.
1.2 通过正则判断是否包含替换符,如果包含则抛出异常
1.3 根据请求方法预处理是否hasBody
1.4 如果包含Headers注解,判断Headers内容是否为空,如果为空抛出@Headers annotation is empty.
1.5 如果包含Multipart注解,判断isFormEncoded是否为True,如果为True抛出Only one encoding annotation is allowed.
1.6 如果包含FormUrlEncoded注解,判断isMultipart是否为True,如果为True抛出Only one encoding annotation is allowed.
1.7 直到如上检查都通过则对relativeUrl(相对路径url),relativeUrlParamNames(相对路径参数)赋值.
ps.也就是只有一种编码注解
代码如下:
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;
}
}
///////////////////////////////////////////////////////////////////////////
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);
}
parseParameterAnnotation()
-
URL注解和PATH注解单独预处理,必须在其他参数之前
-
实在太长了不想解析了,没什么难度,有兴趣的自己去看把
ps.此方法代码近500,不与贴出。
其他预处理,代码如下:
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).");
}
}
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.");}
- 对方法检查是否为空.
- 如果hasBody为false,但是添加了Multipart支持,抛出异常Multipart can only be specified on HTTP methods with request body (e.g., @POST)。也就是限制Multipart下的请求方式。
- 其实还是限制,get请求下不能支持FormUrlEncoded
- 判断参数和真实URL是否为空
- 不含有body的请求不能含有@Body注解
- Form-encoded需要有至少一个@Field
- Multipart方法至少含有一个@Part
HttpServiceMethod.parseAnnotations()
- 直到如上代码执行完毕,会返回RequestFactory对象。然后HttpServiceMethod会调用**parseAnnotations()**方法,传入requestFactory对象。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
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 = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
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.");
}
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这个类其实就是把一个Retrofit接口适配成一个真实的HttpCall,然而parseAnnotations()方法就是关键,分析如下:
-
首先会根据requestFactory.isKotlinSuspendFunction判断是否是一个Kotlin协程方法,如果是的话做出如下处理:
1.1. 如果返回的变量类型是Response,并且是一个参数化类型,记录返回类型的上界并且标记为需要持续响应。
1.2. 然后根据Utils.ParameterizedTypeImpl()方法返回参数类型的真实实例。
1.3. 判断是否有SkipCallbackExecutor注解,去确认是否跳过。
1.4. 如果不是Kotlin协程方法的话,直接通过method.getGenericReturnType()返回参数真实类型。
-
通过createCallAdapter()方法返回真实的CallAdapter,其实调用了retrofit.callAdapter()->nextCallAdapter()方法
2.1. 通过一开始我们分析Retrofit.callAdapterFactories里放的是各种类型的CallAdapter实例,默认已经有了DefaultCallAdapterFactory和CompletableFutureCallAdapterFactory两个CallAdapter。但是我们先分析DefaultCallAdapterFactory。
2.2. 其实这个时候就会通过returnType和annotations从callAdapterFactories取得对应的CallAdapter实例。
2.3. 如果没有找到对应类型的CallAdapter,则会抛出异常.
-
判断响应返回类型是不是okhttp3.Respons,如果是就抛出异常。
-
判断响应返回类型的Response必须指定参数化,不能是一个非参数类型。
-
判断如果请求类型为HEAD,则不能包含返回类型
-
通过createResponseConverter()方法返回真实的ResponseConverter,其实调用了retrofit.responseBodyConverter()->nextResponseBodyConverter()方法
6.1. 同理也是通过returnType和annotations从converterFactories取得对应的ResponseConverter
6.2. 如果没有找到对应类型的ResponseConverter,则会抛出异常
-
如果不是Kotlin协程方法,则会把刚才的requestFactory,callFactory,responseConverter,callAdapter组合成一个CallAdapted
-
如是Kotlin协程方法
8.1. 如果是持续响应方法,则返回SuspendForResponse
8.2. 如果不是持续响应方法,则返回SuspendForBody
DefaultCallAdapterFactory
-
这时我们分析以下上文还未分析的DefaultCallAdapterFactory
我们先看DefaultCallAdapterFactory的get方法,其实大部分代码都是做安全性和准确性检查。关键代码只有最后return的CallAdapter对象,和内部重写的adapt方法。adapt方法会根据传入的executor检查返回ExecutorCallbackCall对象。
@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<Foo> 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<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
get方法的检查内容如下:
1.通过getRawType()方法判断原始类型是否为Call 2.判断返回类型是否为Call的包装类 3.检查是否添加了SkipCallbackExecutor注解,如果添加了则跳过处理 4.通过 Utils.getParameterUpperBound()通过通配符表达式获取到真实的返回类型的上界,但是会在内部做一些安全操作。下方是代码实现
static Type getParameterUpperBound(int index, ParameterizedType type) { Type[] types = type.getActualTypeArguments(); if (index < 0 || index >= types.length) { throw new IllegalArgumentException( "Index " + index + " not in range [0," + types.length + ") for " + type); } Type paramType = types[index]; if (paramType instanceof WildcardType) { return ((WildcardType) paramType).getUpperBounds()[0]; } return paramType; }
至此为止,我们知道adapt方法返回了ExecutorCallbackCall,至于ExecutorCallbackCall具体做了什么,我们先保留。但是了解到DefaultCallAdapterFactory其实就是真实Call对象的转换器。
Proxy.newProxyInstance()
-
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
-
$Proxy0 实现了我们给的接口Sourceable 并且继承了Proxy,构造类要传入我们使用newProxyInstance时用的InvocationHandler变量,并且在static静态初始化中把Sourceable接口的各个方法Method初始化完成(包括equals,toString等方法),并且真正执行方法的时候实际上是执行InvocationHandler对象的invoke()方法(super.h就是保存在父类Proxy中的InvocationHandler对象),各个方法的区别就是Method对象不同而已,所以真正方法的执行是在InvocationHandler的invoke()方法中完成的。 这也说明了代理逻辑 和 动态代理本身是代码分离的,开发者只需要关注好自己的代理逻辑就行,动态代理本身就交给jdk本身去处理。代码如下:
@CallerSensitive public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{ Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } Class<?> cl = getProxyClass0(loader, intfs); try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); cons.setAccessible(true); } return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }- 检查 h 不为空,否则抛异常
- 对传入的接口做安全检查
- 实现动态代理的核心方法,动态代理的思路便是生成一个新类,刚刚getProxyClass0便成为了生成新类
- 根据生成的class通过反射获取构造函数对象并生成代理类实例
-
经过对newProxyInstance方法分析,得出其实就是看invoke的实现,代码跟踪之后找到如下实现
@Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }OkHttpCall
我们分两步,先看生成的OkHttpCall
OkHttpCall( RequestFactory requestFactory, Object[] args, okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) { this.requestFactory = requestFactory; this.args = args; this.callFactory = callFactory; this.responseConverter = responseConverter; }其实非常简单,就是把之前获取的RequestFactory,callFactory,responseConverter都提供给OkHttpCall,这个时候我们就应该能得出了,这个就是真实OkhttpCall。OkHttpCall还有一些方法我们开始分析
-
getRawCall()
private okhttp3.Call getRawCall() throws IOException { okhttp3.Call call = rawCall; if (call != null) return call; if (creationFailure != null) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else if (creationFailure instanceof RuntimeException) { throw (RuntimeException) creationFailure; } else { throw (Error) creationFailure; } } try { return rawCall = createRawCall(); } catch (RuntimeException | Error | IOException e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } private okhttp3.Call createRawCall() throws IOException { okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; }代码实现就如方法名,获取未处理的Call,但是内部还有一些逻辑,例如RequestFactory.create()方法内部的RequestBuilder创建获取过程就不介绍了,代码很简单,大家可以随后看。
-
enqueue()
public void enqueue(final Callback<T> callback) { Objects.requireNonNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } call.enqueue( new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } @Override public void onFailure(okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } }); }这个方法就很熟悉了,其实就是外部开发者调用的enqueue方法具体实现,解析如下:
-
在同步代码块中通过executed判断是否执行过。
-
对rawCall和creationFailure做预处理,rawCall如果为空则通过createRawCall()方法获取(就是我们上文分析的创建过程),如果获取失败则把失败信息赋值给creationFailure
-
如果队列被取消,则通过canceled判断做Call的cancel
-
执行call.enqueue()方法,内部有两个回调
4.1. onResponse() 进入回调则执行parseResponse()方法,方法下文分析,然后调用callback.onResponse(OkHttpCall.this, response)提供给开发者实现
4.1. onFailure() 进入回调则执行callFailure(e),然后调用callback.onFailure(OkHttpCall.this, e)提供给开发之是实现
-
-
parseResponse()
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); rawResponse =rawResponse .newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); if (code < 200 || code >= 300) { try { ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205) { rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }-
通过rawResponse的二次build方法把Okhttp.Response移除,因为rawBody是有状态的对象,防止多次读取,所以先移除
-
如果返回状态码小于200或者大于300会做结果整体缓冲,以避免将来再次请求的I/O负荷
-
如果状态码为204或者205直接返回success,因为204状态码是预检请求,205和204一样,但是要求开发者响应试图
-
ExceptionCatchingResponseBody在创建时其实用到了Okio.buffer()的,我们之后专门分一期讲解OKio
-
然后用之前我们分析的responseConverter的convert()方法转换了开发者需要的返回实体,我们简单看一下GsonResponseBodyConverter的convert()实现
public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return result; } finally { value.close(); } }其实很简单,通过字符流生成jsonReader然后再通过TypeAdapter做类型转换,最后返回开发者需要的类型
-
-
execute()
public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = getRawCall(); } if (canceled) { call.cancel(); } return parseResponse(call.execute()); }- 就是做了同步代码块的是否执行过的处理
在invoke方法内部分析完OkHttpCall的诞生和内部的方法,我们来看最关键的方法,就是adapt(),先回顾一下代码
final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }这里我们还是拿DefaultCallAdapterFactory为分析对象,上文我们分析了get方法,但是还遗留了ExecutorCallbackCall这个内部类和adapt方法
public Call<Object> adapt(Call<Object> call) { return executor == null ? call : new ExecutorCallbackCall<>(executor, call); } static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { Objects.requireNonNull(callback, "callback == null"); delegate.enqueue( new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute( () -> { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on // cancellation. 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(() -> callback.onFailure(ExecutorCallbackCall.this, t)); } }); } @Override public boolean isExecuted() { return delegate.isExecuted(); } @Override public Response<T> execute() throws IOException { return delegate.execute(); } @Override public void cancel() { delegate.cancel(); } @Override public boolean isCanceled() { return delegate.isCanceled(); } @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone. @Override public Call<T> clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); } @Override public Request request() { return delegate.request(); } @Override public Timeout timeout() { return delegate.timeout(); } }-
根据ExecutorCallbackCall的构造得出需要executor和Call两个实例
1.1. executor其实就是上文分析的Platform里的Android的MainThreadExecutor
1.2. Call其实就是传入的代理对象,然而Call本质就是Cloneable
-
然后我们分析enqueue,其实这就是Call也就是Cloneable执行的地方,然后在MainThreadExecutor.execute方法里通过Cloneable的状态去调用callback的对应方法
-
其他还有一些辅助方法,例如isExecuted,execute,cancel,isCanceled,clone,request,timeout,其实就是状态提供实现,值得一提的是clone是深度克隆
-
-
最终概念模型
经过以上分析我们得出梳理下retrofit.create()的概念模型(除去细节)
-
在validateServiceInterface()方法里基于ArrayDeque双向列表实现service的检查管理
-
在loadServiceMethod()方法里通过ServiceMethod.parseAnnotations()方法返回ServiceMethod添加到serviceMethodCache里
2.1. 调用了RequestFactory的parseAnnotations()方法,最终执行了内部的Builder的Buid方法
2.2. 在Buid方法内部通过parseMethodAnnotation()对方法注解做预处理,通过parseParameterAnnotation()方法对参数注解做预处理,还有一些其他处理,最终返回requestFactory
2.3. 把返回的requestFactory传给HttpServiceMethod.parseAnnotations()返回HttpServiceMethod
2.4. HttpServiceMethod.parseAnnotations()方法其实内部判断了是否支持Kotlin协程和一些预处理,再根据返回类型和转换类型把Platform默认提供或者开发者提供的callFactory和responseConverter注入到HttpServiceMethod实例中
-
通过Proxy.newProxyInstance生成动态代理模型,然后在具体的invoke方法之中处理
3.1. invoke的实现其实就是先通过之前的requestFactory,callFactory,responseConverter生成OkHttpCall对象。
3.2. 然后开发者在外部调用.enqueue()方法其实根本就是调用OkHttpCall的enqueue()方法,去执行真实的网络请求
3.3. 在onResponse()方法里通过parseResponse转换为需要的返回类型。
类说明
这个时候整体思路已经完全理清,我们总结下Retrofit涉及到的类与说明
| 类名 | 关键方法 | 说明 |
|---|---|---|
| Retrofit | 内部Builder Builder的addConverterFactory() Builder的addCallAdapterFactory() Builder的build() create() validateServiceInterface() loadServiceMethod() nextCallAdapter() nextResponseBodyConverter() | Retrofit核心类 |
| Platform | findPlatform() defaultCallbackExecutor() defaultCallAdapterFactories() defaultConverterFactories() invokeDefaultMethod() | 平台类,提供java和Android平台,提供了默认的ConverterFactory和CallAdapterFactory和defaultCallbackExecutor |
| ServiceMethod | parseAnnotations() invoke() | 是一个负责转化(适配)的类,负责把一个接口的抽象方法的执行过程的结果转化(适配)成一个网络请求(HTTP call) |
| RequestFactory | parseMethodAnnotation() parseParameterAnnotation() | 对接口的方法注解和参数注解做相关预处理 |
| HttpServiceMethod | parseAnnotations() createCallAdapter() createResponseConverter() | 根据接口方法返回类型做CallAdapter和ResponseConverter的预处理 |
| OkHttpCall | getRawCall() enqueue() parseResponse() | 真实Okhttp的实例以及call调用处理和转换处理 |