本文基于Retrofit2的2.4.0版本缓存
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
复制代码
咱们在发起异步网络请求时是这样调用的:bash
MyService myService = retrofit.create(MyService.class);
Call<IpBean> call = myService.getData();
call.enqueue(new Callback<IpBean>() {
@Override
public void onResponse(Call<IpBean> call, Response<IpBean> response) {
}
@Override
public void onFailure(Call<IpBean> call, Throwable t) {
}
});
复制代码
总结起来就是三步:经过create方法生成咱们的接口对象、调用接口获得Call、调用Call发起网络请求。咱们分别来看看这三步Retrofit2都干了些啥。微信
//Retrofit.class
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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, @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);
}
//这里默认返回是false,因此不会执行
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);
//返回通过适配器适配后的okHttpCall
return serviceMethod.adapt(okHttpCall);
}
});
}
复制代码
能够看到Retrofit的create方法返回的是一个动态代理对象,当咱们调用经过create方法生成的接口对象myService时,就会调用代理对象的invoke方法。在invoke方法中作了几件事:网络
(1)根据调用的具体方法Method(好比咱们调用的getData方法),生成ServiceMethod异步
(2)用生成的ServiceMethod和方法中的参数生成OkHttpCall用于后面调用OkHttp3请求网络ide
(3)将生成的OkHttpCall经过Call适配器适配之后返回,也就是将OkHttpCall转换成须要的Call类型,好比Retrofit2的Call,RxJava的Observable等,供咱们调用。post
咱们调用接口myService的getData方法时,会调用上面提到的动态代理对象的invoke方法,invoke方法会分别建立ServiceMethod、OkHttpCall,并将OkHttpCall适配返回咱们须要的Call对象。下面咱们来深刻源码看看Retrofit是怎么作这些事儿的。ui
(1)首先咱们看看是怎么建立ServiceMethod的。this
//Retrofit.class
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
复制代码
Retrofit中利用ConcurrentHashMap对ServiceMethod进行了缓存,建立ServiceMethod时会先去缓存中找,缓存中没有的话再调用ServiceMethod的Builder建立。由于Retrofit会为咱们写的接口类中的每个方法都建立一个ServiceMethod,因此ServiceMethod的数量会不少,利用缓存能够提升效率。spa
public ServiceMethod build() {
//找到该方法所须要的CallAdapter
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
...
//找到该方法须要的返回类型转换器
responseConverter = createResponseConverter();
//解析方法中的注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...
//这里省略解析参数中的注解步骤
...
return new ServiceMethod<>(this);
}
复制代码
ServiceMethod的build方法中除了解析方法和参数的注解,最重要的就是肯定该方法(每个方法对应一个ServiceMethod)的CallAdapter和ResponseConverter。咱们在构建Retrofit时能够添加多个CallAdapter和ResponseConverter,而这些CallAdapter和ResponseConverter都存放在Retrofit的对应的列表中,因此这里确定须要去Retrofit的列表里找,咱们来看看。
//ServiceMethod.class
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//经过retrofit的callAdapter方法来查找对应的CallAdapter
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
复制代码
能够看到这里确实是经过retrofit来查找CallAdapter的,那咱们去Retrofit的callAdapter方法方法看看
//Retrofit.class
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}
复制代码
callAdapter方法中会遍历callAdapterFactories列表中的CallAdapterFactory,并调用其get方法,尝试获取CallAdapter,若是CallAdapter不为null,就说明是要找的CallAdapter。这里咱们来简单看下默认的CallAdapterFactory的get方法。
从本文的开头的分析咱们知道,默认的CallAdapterFactory是Platform的内部类Android返回的ExecutorCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
...
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
...
}
...
}
复制代码
能够看到,ExecutorCallAdapterFactory的get方法首先会判断当前的返回类型是否是Call以及Call的子类,不是的话就返回null。因此这就是Retrofit从适配器列表中找到对应适配器的方法依据。好比咱们再来看看RxJava的适配器:
//RxJavaCallAdapterFactory.class
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
...
return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
false);
}
复制代码
因此当咱们接口须要的是Observable时,咱们就须要给Retrofit设置RxJava的适配器,这样Retrofit在建立ServiceMethod时就能找到对应的RxJava适配器了。
(2)建立OkHttpCall
建立OkHttpCall比较简单,直接调用构造方法就行
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
复制代码
(3)返回接口须要的Call对象
从上面的分析中咱们知道,是经过serviceMethod的adapt方法来返回目标Call对象的,那咱们来看看serviceMethod的adapt方法
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
复制代码
能够看到调用的serviceMethod中的callAdapter的adapt方法,也就是在上面的建立ServiceMethod的过程当中肯定的CallAdapter的adapt方法。这里咱们看看默认的CallAdapter的adapt方法,也就是ExecutorCallAdapterFactory的adapt方法
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
...
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, 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) {
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()) {
// 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(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); } @Override public Response<T> execute() throws IOException { return delegate.execute(); } ... } } 复制代码
能够看到,ExecutorCallAdapterFactory的adapt方法返回的是ExecutorCallAdapterFactory的内部类ExecutorCallbackCall,ExecutorCallbackCall内部有2部分组成,一个是回调执行器callbackExecutor,这个是用于将请求结果回调到主线程的;另外一是Call对象,这里对应的就是OkHttpCall,由于咱们调用adapt方法传入的就是OkHttpCall。
因此到这里其实网络调用的前半部分流程就清楚了:
咱们在调用咱们的接口方法myService的getData方法时,实际上调用的是Retrofit为咱们生成的代理类的invoke方法,invoke方法会建立ServiceMethod和OkHttpCall,ServiceMethod中保存着对应CallAdapter和ResponseConverter,而后会调用ServiceMethod中的adapt方法利用CallAdapter将OkHttpCall转换成咱们须要的Call类型并返回给咱们调用。当咱们调用Call进行网络请求时实际上调用的就是OkHttpCall对应的方法。
下篇文章咱们再来分析下网络调用的下半部分流程,也就是Retrofit是怎么将OkHttp3请求返回的Response转换成咱们实际须要的类型的?
欢迎关注个人微信公众号,和我一块儿天天进步一点点!
复制代码