2016/07/21
上海
Read the fucking source code。
Retrofit,Type-safe HTTP client for Android and Java 。
GitHub:http://square.github.io/retrofit
开始之前,先回想下一个网络请求的基本姿势(默认框架搭建完成):
1,生成请求参数,确定接口
2,利用NetWork模块,发送到指定API
3,响应成功,反序列
4,响应失败,做某些处理
5,线程调度,结果交给前台
Retrofit作为NetWork框架,也不例外。
1,以接口+注解的形式,生成请求参数,确定接口
2,利用CallFactory生成NetWork模块,发送到指定API
3,响应成功,利用ConverterFactory反序列
4,响应失败,做某些处理
5,请求结果经过CallAdapterFactory包装
6,CallAdapterFactory包装包装后,线程调度,结果交给前台
目录:
1,我们配置Retrofit时,到底发生了什么?
2,Retrofit.create(final Class
3,ServiceMethod 是什么?
4,OkHttpCall 是什么?
5,serviceMethod.callAdapter.adapt(okHttpCall)是什么鬼?
6,CallFactory、okHttpCall、CallAdapter之间的关系?
问题一:我们配置Retrofit时,到底发生了什么?
//Retrofit构造器
new Retrofit.Builder()
//配置服务器
.baseUrl(UrlHelp.SERVER_IP)
//反序列工具生成器
.addConverterFactory(XmlToJsonConverterFactory.create())
.//结果包装工具生成器(不大好描述..)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//NetWork工具生成器
.callFactory(HttpClient())
//线程调度
.callbackExecutor()
.build();
** 配置:**
ConverterFactory 反序列工具生成器
CallAdapterFactory 结果包装工具生成器 默认为ExecutorCallAdapterFactory
okhttp3.Call.Factory NetWork工具生成器 默认为OkHttpClient
CallbackExecutor 线程调度
配置的是Retrofit的功能模块,Retrofit将网络请求流程中的各个关节(是的,关节)部位打断,使各个模块之间相关性降到最低,再通过“配置”的方式开放出来,应对复杂的使用环境。
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List converterFactories,
List adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories);
// Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories);
// Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
.build()方法new Retrofit()实例并返回,new Retrofit()时传入配置信息。
问题二:Retrofit.create(final Class service)都做了什么?
mRetrofit.create(RetorfitInterfaces.UserInfoServer.class)
.sendPost(userId)
.enqueue(call);
create(final Class
在外部使用中,这是最直接的感受,实际上返回的是代理对象。
//仅摘取核心部分
public T create(final Class service) {
......
return (T) Proxy.newProxyInstance(
...
new InvocationHandler() {
.....
@Override
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
......
//加载ServiceMethod
ServiceMethod serviceMethod = loadServiceMethod(method);
//加载OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//调用callAdapter.adapt(okHttpCall)
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
这部分源码写的很直观,简单来说当调用接口中的方法时,都会运行InvocationHandler的invoke()方法。
重点就在invoke(Object proxy, Method method, Object... args)方法中的三句代码:
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
问题三:ServiceMethod 是什么?
(以下省略适配、优化等细节代码)
//调用Retrofit.loadServiceMethod(method);加载ServiceMethod;
serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
....
//通过 ServiceMethod.Builder构造器创建实例
result = new ServiceMethod.Builder(this, method).build();
....
return result;
}
public Builder(Retrofit retrofit, Method method) {
//持有了retrofit实例,retrofit持有前面说到的各配置组件,
//也就是说ServiceMethod相当于持有各配置组件,
//变相的将四大组件组装在了一起。
this.retrofit = retrofit;
..注解解析相关...
}
public ServiceMethod build() {
.....
//创建CallAdapter实例,createCallAdapter()是ServiceMethod.Builder的私有方法,在此简写
callAdapter = createCallAdapter(){
....
//调用了Retrofit实例的CallAdapter();CallAdapter()是Retrofit的公共方法,在此简写
return retrofit.callAdapter(returnType, annotations){
...
//Retrofit利用配置中的CallAdapterFactory获取CallAdapter实例
return CallAdapterFactory.get();
};
};
......
//创建responseConverter 反序列工具实例,createResponseConverter()是ServiceMethod.Builder的私有方法,在此简写
responseConverter = createResponseConverter(){
....
//调用Retrofit实例的responseBodyConverter()方法
return retrofit.responseBodyConverter(responseType, annotations){
....
//利用converterFactory工厂创建反序列工具
return converterFactory.responseBodyConverter();
}
};
...注解相关...
//调用ServiceMethod的构造函数ServiceMethod(Builder builder);创建实例
return new ServiceMethod<>(this);
}
//ServiceMethod.Builder构造器(注意还不是ServiceMethod)持有了Retrofit实例,CallAdapter实例,responseConverter 反序列工具实例。
//ServiceMethod构建方法,参数是构造器
ServiceMethod(Builder builder) {
this.callFactory = builder.retrofit.callFactory();//持有CallFactory实例
this.callAdapter = builder.callAdapter; //持有CallAdapter实例
this.baseUrl = builder.retrofit.baseUrl(); //持有BaseUrl
this.responseConverter = builder.responseConverter;//持有反序列工具
....注解相关
}
至此,ServiceMethod实例创建完毕,ServiceMethod变相的将各模块组装在一起。
问题四:OkHttpCall是什么?
先说两个概念:
interface okhttp3.Call{
enqueue(Callback responseCallback);
execute();
request();
isExecuted();
isCanceled();
cancel();
}
interface retrofit2.Call{
同上;
clone();
}
1,retrofit2.Call与okhttp3.Call区别就是多了个clone方法,retrofit2.Call需要clone,才能再次使用。
2,OkHttpCall 实现了retrofit2.Call。
3,CallFactory创建的是okhttp3.Call实例,OkHttpClient实现了okhttp3.Call。
WTF??看代码。
(以下省略适配、优化等细节代码)
//直接调用构造方法
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall(ServiceMethod serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod; //持有了ServiceMethod实例
this.args = args;//注解相关
}
OkHttpCall持有serviceMethod实例,就这样。但OkHttpCall 实现了retrofit2.Call,有必要看一下enqueue(Callback responseCallback);execute();
//外部传入callBack,结果回调
enqueue(final retrofit2.Callback outCallback){
//Retrofit NetWork模块实际使用的还是okhttp3.Call,retrofit2.Call只是对外放出的包装
okhttp3.Call call = createRawCall(){
//Retrofit 默认callFactory为OkHttpClient
return serviceMethod.callFactory.newCall(request);
};
//利用okhttp3.Call发送请求,并传入新的CallBack();
call.enqueue(
new okhttp3.Callback() {
//成功
onResponse(okhttp3.Response rawResponse){
//parseResponse(rawResponse)是将请求结果反序列,内部调用ServiceMethod中的responseConverter,也就是配置里的反序列化工具生成JavaBean。
rawResponse = parseResponse(rawResponse)
//将反序列化后的JavaBean传给前台
outCallback.onResponse(rawResponse);
}
//失败
onFailure(Throwable e){
//将错误信息传给前台
outCallback.onFailure(e);
}
}
)
}
execute(){
...与enqueue大致相同, 也是利用CallFactory生成okhttp3.Call,调用okhttp3.Call.execute()
}
so:
1,OkHttpCall实现Retrofit.Call接口
2,CallFactory生成的Call对象为Okhttp3.Call接口
3,OkHttpCall持有CallFactory生成的Call对象
4,OkHttpCall在enqueue,execute方法中实际调用的是CallFactory生成的Call对象发送请求,OkHttpCall本身并没有NetWork的功能
5,所以,OkHttpCall只是适配器,或者说包装器,外部使用Retrofit.Call,Retrofit.Call内部使用Okhttp3.Call,Retrofit.Call与Okhttp3.Call之间,由OkHttpCall调度
6,OkHttpCall实现Retrofit.Call接口,与外部来说,无需关心NetWork到底是如何发送的
问题五:
serviceMethod.callAdapter.adapt(okHttpCall)是?
先回头撸一下
mRetrofit
//返回代理对象
.create(RetorfitInterfaces.UserInfoServer.class)
//serviceMethod.callAdapter.adapt(okHttpCall)返回retrofit2.Call对象
.sendPost(userId)
//调用返回的retrofit2.Call的enqueue方法
.enqueue(call);
没毛病。
serviceMethod.callAdapter由Retrofit.CallAdapterFactory创建(上面源码有提到)。 而CallAdapterFactory可由外部配置,默认ExecutorCallAdapterFactory。
(以下省略适配、优化等细节代码)
//默认ExecutorCallAdapterFactory.adapt,创建返回了ExecutorCallbackCall实例
@Override public Call adapt(Call call) {
//call就是okHttpCall
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
//看看ExecutorCallbackCall又是什么,一个 Retrofit2.Call实现类,
class ExecutorCallbackCallimplements Retrofit2.Call{
//构造函数,callbackExecutor配置中的线程池,delegate就是okHttpCall
ExecutorCallbackCall(Executor callbackExecutor, retrofit2.Call delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; }
//Retrofit2.Call接口中的方法,发送异步请求,参数outCallBack是外部传入的回调接口
enqueue(final Callback outCallback){
//利用delegate,其实就是okHttpCall发送请求,又是包装new Callback()
delegate.enqueue(new Callback() {
//成功
onResponse(Call call, final Response response) {
//线程调度
callbackExecutor.execute(new Runnable() {
public void run() {
//传给前台
outCallBack.onResponse(
ExecutorCallbackCall.this, response
);
}
}
}
//失败
onFailure(Call call, final Throwable t){
//线程调度
callbackExecutor.execute(new Runnable() {
public void run() {
outCallBack.onFailure(ExecutorCallbackCall.this, t);
}
});
}
);
}
// ****Retrofit2.Call接口中的方法,**发送同步请求**
Response execute(){
//delegate 就是okHttpCall
return delegate.execute();
}
}
1,serviceMethod.callAdapter.adapt(okHttpCall)返回Retrofit2.Call实例,默认ExecutorCallbackCall
2,ExecutorCallbackCall实例中持有okHttpCall的实例
3,ExecutorCallbackCall实例中的enqueue,execute方法,方法中实际操作的还是OkHttpCall对应的方法。
4,ExecutorCallbackCall将请求结果通过制定线程(配置中的CallbackExecutor)发送到前台
问题六:CallFactory、okHttpCall、CallAdapter之间的关系?
从上向下的包装关系,,类似装饰模式:
** 外部调用**
** CallAdapterFactory.CallAdapter.Retrofit.Call**
** 包装**
okHttpCall.Retrofit.Call
** 包装**
CallFactory.okhttp3.Call
外部调用
|---------------------------------------------------|
| CallAdapter.Retrofit.Call |
| |---------------------------------------| |
| | okHttpCall.Retrofit.Call | |
| | ----------------------------- | |
| | | CallFactory.okhttp3.Call | | |
| | ----------------------------- | |
| | | |
| |---------------------------------------| |
| |
|---------------------------------------------------|
CallFactory.okhttp3.Call面向发送请求,不关心结果处理
CallAdapterFactory.CallAdapter.Retrofit.Call面向返回结果,不关心发送
OkHttpCall.Retrofit.Call作为中间件,将两者联系起来
**外部实际调用的是CallAdapter生成的Retrofit.Call **