本文将以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发起网络恳求。