本文将以retrofit使用流程的角度来讲解retrofit的设计原理。(建议先看目录,再阅读文章)
先讲一下"上古时代"retrofit的用法。
后端文档:
- 接口 www.wanandroid.com/hotkey/json
- 请求方式 GET
- 响应示例
{
"data": [{
"id": 8,
"link": "",
"name": "逆向 加固",
"order": 8,
"visible": 1
}],
"errorCode": 0,
"errorMsg": ""
}
客户端开发:
一,基本使用流程
1,定义响应数据bean
//对应响应的数据结构
class ApiResult<T> {
var errorCode: String? = null
var errorMsg: String? = null
var data: T? = null
}
//对应data的数据结构
data class Info(
val id: Int? = 0,
val name: String? = "",
val link: String? = "",
val order: Int? = 0,
val visible: Int? = 0
)
2,定义描述网络请求的接口
interface HotKeyApiInterface {
@GET("/hotkey/json")
fun getDataWithCall(): Call<ApiResult<List<Info>>>
}
3,创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
4,创建步骤2中描述网络请求接口的代理
val apiProxy = retrofit.create(HotKeyApiInterface::class.java)
5,创建网络请求Call
val call: Call = apiProxy.getDataWithCall()
6,进行同步请求或异步请求
//进行同步请求
val response = call.execute()
val apiResult = response.body() //得到我们定义的ApiResult
//进行异步请求
call.enqueue(object : Callback<ApiResult<List<Info>>> {
override fun onResponse(
call: Call<ApiResult<List<Info>>>,
response: Response<ApiResult<List<Info>>>
) {
val apiResult = response.body() //得到我们定义的ApiResult
}
override fun onFailure(call: Call<ApiResult<List<Info>>>, t: Throwable) {
TODO("Not yet implemented")
}
})
二,retrofit中的注解类型
从上面步骤2定义描述网络请求接口的代码为:
interface HotKeyApiInterface {
@GET("/hotkey/json")
fun getDataWithCall(): Call<ApiResult<List<Info>>>
}
这里用@GET注解描述当前请求的请求方式为GET请求,请求路径为"hotkey/json"。
retrofit中就是用注解来描述我们的请求行为:如请求方式、请求参数等,然后在运行期间,通过解析注解封装一个请求request,request中会携带请求头、请求地址、请求方式等信息,最终调用okhttp完成真正的请求。
总体来说,retrofit主要有三类注解:
1,描述网络请求方式的注解
@GET,@POST,@DELETE等
2,描述网络请求参数的注解
@HEAD,@Field,@Query等
3,其他类型注解
@Multipart,@Streaming,@FormUrlEncode
三,retrofit中的重要组件
查看retrofit的源码:
public final class Retrofit {
final okhttp3.Call.Factory callFactory;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
...
}
上面列举了retrofit有几个重要的组件,我们可以使用retrofit默认提供的这些组件实现,或者在实例化retrofit的时候,给它设置我们自定义的组件实现,这些组件的具体原理在后面会详细讲解。
1,callFactory
自定义配置的okHttpClient,retofit本身实际上并没有进行网络请求的能力,它依赖OkHttp完成网络请求。
2,converterFactories
数据转换器,用来将okhttp返回的response转换成我们自定义的数据bean。
3,callAdapterFactories
适配器,适配器的返回值决定着上面步骤二中接口的返回值。
4,callbackExecutor
回调执行器,切换到主线程回调结果。
四,动态代理
上面步骤4 创建了描述网络请求接口的代理,代码如下:
val apiProxy = retrofit.create(HotKeyApiInterface::class.java)
查看retrofit#create方法的源码:
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);
}
});
}
create方法调用Proxy.newProxyInstance()为接口HotKeyApiInterface生成动态代理,Proxy.newProxyInstance()源码如下,它是java提供的动态创建代理的api,接受三个参数:
- classLoader:类加载器。
- interfaces: 接口的class数组,创建的动态代理会实现这里的接口。
- InvocationHandler:类InvocationHandler的一个实现,后面会分析这个类的作用。
public static Object newProxyInstance(
@RecentlyNullable ClassLoader loader,
@RecentlyNonNull Class<?>[] interfaces,
@RecentlyNonNull InvocationHandler h) throws IllegalArgumentException {
...
}
上面的动态代理会生成一个代理类Proxy,这里的代理类并不是一个java文件,而是一个class文件,因为动态代理是在运行期间生成代理类的,代理类的class文件反编译成java文件后,代码大致如下。
//生成的代理类的源码
public final class $proxy0 extend Proxy implements HotKeyApiInterface {
public $Proxy0(InvocationHandler handler) {
super(handler); //这里的handler就是上面我们传的第三个参数InvocationHandler,会赋值给它的父类Proxy的属性h
}
public final Call<ApiResult<List<Info>>> getDataWithCall() {
this.h.invoke( ... ) //这里的h为上面传进来的第三个参数InvocationHandler
}
...
}
//系统类Proxy的源码
public class Proxy implements Serializable {
protected InvocationHandler h;
...
}
总结一下:上面声明的apiProxy为$Proxy0的实例,即动态代理生成的代理类继承自Proxy且实现了我们自定义的接口HotKeyApiInterface。
五,适配器CallAdapter
上面步骤5 创建网络请求Call的代码如下:
val call: Call = apiProxy.getDataWithCall()
从前面文章的分析中可以知道,这里生成的apiProxy就是动态代理类 $Proxy0,它继承自Proxy且实现了接口HotKeyApiInterface,所以这里的调用流程为:
- 调用apiProxy#getDataWithCall方法。
- 即执行代理类的getDataWithCall方法。
- 步骤2的方法内部执行InvocationHandler的invoke方法,也就是会执行Retrofit#create方法中创建的InvocationHandler#invoke方法。
接着看InvocationHandler#invoke方法,源码如下:
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); //关键点1
}
});
}
看关键点1处:执行loadServiceMethod方法的返回值invoke方法,即HtttpServiceMethod#invoke方法(怎么得出HtttpServiceMethod,大家可以自行调试):
//HtttpServiceMethod#invoke
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
//HtttpServiceMethod#adapter
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
所以,HtttpServiceMethod#adapter的返回值就是我们apiProxy.getDataWithCall()的返回值,adapter为一个抽象方法,它的实现类有三个:
- HtttpServiceMethod.CallAdapted:当apiProxy.getDataWithCall的返回值为Call的情况。
- HtttpServiceMethod.SuspendForResponse:这个是用来适配retrofit结合suspend,且返回值为Response的情况。
- HtttpServiceMethod.SuspendForBody:这个是用来适配retrofit结合suspend,且返回值为自定数据bean的情况。
上面的2, 3后续会单独出文章进行讲解,由于我们定义接口HotKeyApiInterface#getDataWithCall的返回类型为Call,所以这里HtttpServiceMethod#adapter方法的实现类为CallAdapter,看看它的源码:
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) { //关键点1
return callAdapter.adapt(call); //关键点2
}
}
上面代码的关键点1处:这里又有一个callAdapter,这个callAdapter才是我们要讲解的适配器CallAdapter,它在retrofit中的默认实现为:
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
@Nullable
private final Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Nullable
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
} else if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
} else {
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType)returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : this.callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
public Type responseType() {
return responseType;
}
public Call<Object> adapt(Call<Object> call) { //关键点1
return (Call)(executor == null ? call : new ExecutorCallbackCall(executor, call));
}
};
}
}
看关键点1处,它返回一个ExecutorCallbackCall的实例,看它的源码:
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();
}
}
ExecutorCallbackCall实现了接口Call,是Call类型,它其实是一个代理类,包含着真正的Call(OkHttpCall,retrofit中的),它就是我们的apiProxy.getDataWithCall()的返回值。
六,网络请求Call
1,网络请求Call是什么
由前面的分析可知apiProxy.getDataWithCall()返回的是ExecutorCallbackCall,它的源码如下:
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate; //关键点1
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();
}
}
关键点1处:这个delegate是Retrofit中的OkHttpCall,源码如下:
final class OkHttpCall<T> implements Call<T> {
private final RequestFactory requestFactory;
private final Object[] args;
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, T> responseConverter;
private volatile boolean canceled;
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall; //关键点2
@GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
private @Nullable Throwable creationFailure;
@GuardedBy("this")
private boolean executed;
}
看关键点2处:这个rawCall是Okhttp中的call。
总结一下:
- apiProxy.getDataWithCall()返回的call是ExcutorCallbackCall。
- ExcutorCallbackCall持有Retrofit中的OkHttpCall。
- Retrofit中的OKhttpCall持有OkHttp的Call。
- Retrofit发起网络请求实际最终调用的是OkHttp的Call发起网络请求。