android中较为火热的网络库当数OkHttp和Retrofit了,它们都来自Square,为什么同样的网络库要做两种?OkHttp与Retrofit之间又有什么联系?我们一步步,揭开Retrofit的源码看看它到底与OkHttp有什么区别!
Retrofit的使用与OkHttp有些许不同

OkHttp中需要请求的相关信息由Request对象承载

而在Retrofit中每一个请求由方法表示,方法的参数和注解信息为相关的请求信息,且方法必须定义在接口类中



同步请求时,不能够阻塞主线程
和OkHttpClient类有点类似,根据之前的经验直接进入Retrofit.Builder内部类中
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();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
通过构建者模式实例化Retrofit对象返回,build方法中做了初始化工作,几个关键的对象被实例化
-
baseUrl:网络请求的基地址
-
callFactory:okhttp中的okhttp3.Call.Factory类用于生成call对象的工厂,用于实际的网络请求
-
callbackExecutor:Executor类的实例化对象,由默认平台生成,用于任务执行的具体工人,但并不是所有都会用到!(这里挖个坑)
-
callAdapterFactories:集合类存放CallAdapter.Factory对象,区分callAdapter和Factories,callAdapter是call的适配器,Factories则是产生适配器的工厂们,注意复数形式
-
converterFactories:集合类存放Converter.Factory对象,区分converter和Factories,converter是类型转换器(如JSON与java对象间的转换),Factories则是生产converter的工厂们

创建的Retrofit对象持有以上几个变量
Retrofit中没有Request对象承载请求信息,转而使用接口
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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
通过动态代理的方式,生成对应的接口对象
前面所说:每一个请求对应接口类中的一个方法。接口被动态代理生成接口对象,当接口对象调用其中的方法时意味着一次请求,由于接口对象是代理对象,那具体的方法执行由代理方法执行

即方法的执行进入代理方法内,代理方法返回call对象,和OkHttp一样是具体的请求,请求结果Response就是call通过execute、enqueue返回的。
咦?怎么这次到这就没了,OkHttp的时候不是深度阅读么,这次怎么是广度阅读了?
首先Retrofit不同于OkHttp是正儿八经的网络库,它只是OkHttp的应用封装,没有OkHttp的请求信息处理、路由、返回码处理、重连、重定向、Cache等众多的网络功能。看OkHttp源码时要深入到网络情况的各种细节,而对于Retrofit要从封装的角度看待源码,了解为什么作者这样封装,采用了这种设计模式的精妙之处在哪里。
封装的几大关键类
- ServiceMethod 接口中每一个方法对应的实际对象
- OkHttpCall Retrofit中的Call类,有请求相关的信息
- okhttp3.Call.Factory 这是okhttp中的类,生产call的工厂,Retrofit默认值是OkHttpClient
- Converter.Factory 转换类的工厂
- CallAdapter.Factory call适配器的工厂,将call适配成不同的功能

网络请求时代理对象调用接口方法,生产call对象。call对象是serviceMethod将okHttpCall对象交给callAdapter适配得来的
这里以RxJavaCallAdapterFactory特定的CallAdapter.Factory来分析,它产生的是RxJavaCallAdapter类。
serviceMethod通过adapt方法将okHttpCall适配成rxCall,具体实现类是RxJavaCallAdapter

就是将call转换成observable类型,当call执行execute时

生产call

call是通过ServiceMethod中callFactory产生的

callFactory默认就是okHttpClient,代码中的RequestBuilder也是OkHttp中的类
至此原本的OkHttpCall经过RxJavaCallAdapter的适配和okHttpClient的生成,已经可以正常的发起请求了。

OkHttp网络库做了实际的网络请求取得response对象

response对象又使用serviceMethod中的converter对象(GsonConverterFactory生成的)转换成需要的类型返回

总结
1、ServiceMethod对应每一个请求,主要功能有:
- 产生实际请求的okhttp3.Call对象
- 适配okhttp3.Call对象
- 将okhttp3.Call对象请求返回的response转换成java对象
2、OkHttpCall是Retrofit中的Call,有相关的网络功能,但其实际是okhttp3.Call的封装类,具体的网络请求都是由okhttp3.Call完成

至于以上三个类都是ServiceMethod内所持有的对象,通过接口中定义方法的具体参数,以泛型的方式传到具体的对象内持有。
此三类都是工厂模式中的工厂,实际的操作在工厂的产出类内部实现。
回到标题,Retrofit做了什么,就是对OkHttp的封装,将call封装成支持Rx(或其他的形式),并将response通过Gson(或其他序列化协议)转成泛型的实际java对象
填坑
前面挖了个坑callbackExecutor,大部分资料都是讲其用于线程间切换的,以及如何切换的,就是下图

但具体是怎么切换的?为什么call.enqueue的回调就默认回到主线程了?
文中使用了RxJavaCallAdapterFactory其实有些误导,我也不打算把这个答案写出来,给几个提示!
1、接口返回类型

2、call适配过程

3、CallAdapter选择的依据


网友评论