Retrofit2源码解析
Retrofit网络请求的功能实现是okhttp3,由okhttp3做真正的网络请求。Retrofit2框架和其他的用于网络请求的框架流程大体相同,Retrofit2优势在于,它使用了大量的设计模式将功能模块解耦,这样做的好处在于可以让流程更加清晰,可塑性更强。
请求过程伪代码:
val retrofit = Retrofit.Builder()
.baseUrl(SERVER_ADDRESS)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(mOkHttpClient)
.build()
var service = retrofit.create(MyService.class)
service.getData()
流程图
请求流程
1、创建Retrofit实例;
2、创建网络请求接口和相关属性注解;
3、通过动态代理解析请求接口的注解,并生成网络请求对象;
4、通过CallAdapter进行平台适配;
5、通过OkHttpCall发送网络请求;
6、通过Converter数据转换适配器转换请求返回的数据;
7、通过线程切换执行器切换到主线程(仅限异步请求)。
源码分析
Retrofit部分代码:
public final class Retrofit {
//网络请求缓存,如:请求方法、请求头、请求体,各种适配器等
private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();
//okhttp工厂,真正发送交易的处理类
private final okhttp3.Call.Factory callFactory;
//请求url域名
private final BaseUrl baseUrl;
//数据转换器工厂集
private final List<Converter.Factory> converterFactories;
//网络请求适配器工厂集
private final List<CallAdapter.Factory> adapterFactories;
//异步请求结果线程切换执行器
private final Executor callbackExecutor;
//标志位、是否马上解析接口方法
private final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories;
this.adapterFactories = adapterFactories;
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
}
Retrofit内部类Builder代码:
Retrofit通过建造者模式进行创建并设置属性,所以Builder类中与Retrofit类属性相同。
public static final class Builder {
private okhttp3.Call.Factory callFactory;
private BaseUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
}
调用build方法:
public Retrofit build() {
//创建retrofit前对baseurl进行非空判断
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
//创建okhttpClient,并赋予callFactory成员变量
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
调用Retrofit的构造方法,创建一个Retrofit实例,通过建造者模式设置并初始化属性。
retrofit.create():
在创建好网络请求服务接口MyService类后,调用retrofit.create(MyService::class.java),这个方法是Retrofit的核心,内部采用动态代理,将咱们自定义的网络请求接口转换成一个ServiceMethod对象,ServiceMethod就是咱们Retrofit中的具体请求对象,里面封装了网络请求所必须的全部信息,包括请求方法、url、请求头、请求体等网络配置参数。
create方法代码:
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, 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);
}
return loadMethodHandler(method).invoke(args);
}
});
}
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
// 将传入的ServiceMethod对象加入LinkedHashMap<Method, ServiceMethod>集合
loadMethodHandler(method);
}
}
}
如果validateEagerly提前验证的标志位为true,将会调用eagerlyValidateMethods(service)方法。传入service接口,通过反射获取内部方法。isDefaultMethod默认为false,因此loadServiceMethod(method)方法一定会走到。
isDefaultMethod方法代码:
boolean isDefaultMethod(Method method) {
return false;
}
loadMethodHandler代码:
private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();
MethodHandler loadMethodHandler(Method method) {
MethodHandler handler;
synchronized (methodHandlerCache) {
handler = methodHandlerCache.get(method);
// 即创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例
// 若没缓存,则通过建造者模式创建 serviceMethod 对象
if (handler == null) {
handler = MethodHandler.create(this, method);
methodHandlerCache.put(method, handler);
}
}
return handler;
}
创建OkHttpCall对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall部分代码:
final class OkHttpCall<T> implements Call<T> {
private okhttp3.Call rawCall;
@Override public void enqueue(final Callback<T> callback) {
}
@Override public Response<T> execute() throws IOException {
}
}
内部维护了一个okhttp3.Call rawCall的对象,接着看下面两个方法:enqueue()和execute(),可以看到内部调用的是rawCall的对应方法,也就是调用okhttp3.Call的enqueue()和execute()。
GsonConverterFactory
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
}
GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory()
Retrofit中addConverterFactory代码:
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
放入到数据转换器工厂converterFactories里,可用retrofit的默认Gson来解析,也可以自定义解析器。
CallAdapter
定义:网络请求执行器(Call)的适配器。
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
把response封装成rxjava的Observeble,然后进行流式操作。
将response适配为Observable对象:
static final class ResultCallAdapter implements CallAdapter<Observable<?>> {
private final Type responseType;
ResultCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override public Type responseType() {
return responseType;
}
@Override public <R> Observable<Result<R>> adapt(Call<R> call) {
return Observable.create(new CallOnSubscribe<>(call)) //
.map(new Func1<Response<R>, Result<R>>() {
@Override public Result<R> call(Response<R> response) {
return Result.response(response);
}
})
.onErrorReturn(new Func1<Throwable, Result<R>>() {
@Override public Result<R> call(Throwable throwable) {
return Result.error(throwable);
}
});
}
}
总结
创建过程
动态创建网络请求接口的实例(代理模式 - 动态代理)
创建 serviceMethod 对象(建造者模式 & 单例模式(缓存机制))
对 serviceMethod 对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 & 数据转换器。(策略模式)
对 serviceMethod 对象加入线程切换的操作,便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理(装饰模式)
最终创建并返回一个OkHttpCall类型的网络请求对象
请求过程:
1.Retrofit 将 Http请求 抽象 成 Java接口
2.在接口里用 注解 描述和配置 网络请求参数
3.用动态代理 的方式,动态将网络请求接口的注解 解析 成HTTP请求
4.最后执行HTTP请求