Android日记之Retrofit源码解析
前言
别问我为啥先写Retrofit的源码解析而不是okhttp的源码解析,主要是最近这几次面试Retrofit被问到的比例相当的大,所以就先写Retrofit的(其实主要是okhttp在项目上已经用上了,面试官也就懒得问了-_-||),我们老样子,从怎么使用这个框架的地方开始入手源码,Retrofit的使用方法可以看Android日记之Retrofit初探,这里的Retrofit版本是2.5。
Retrofit的构建
Retrofit的Builder()方法
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
......
}
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
......
}
里面主要多了一个Platform,它其实是一个很重要的东西,主要是调用了Platform的get()
方法来进行赋值,然后调用里面的findPlatform()
方法,这里面主要就是看你是哪个平台的,通过Class.forName来查找指定的类,然后返回一个Android对象(在Android使用肯定是这个的啦),至于这个Android里面主要干了什么,看了下源码,只知道是跟Retrofit要构建的变量Executor有关,看了下其他论坛的讲解,迷迷糊糊的,还是看不懂,以后再看-_-||。
Retrofit的build()方法
//创建Retrfit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://wanandroid.com/wxarticle/chapters/json/")
.addConverterFactory(GsonConverterFactory.create())
.build();
//build方法源码
public Retrofit build() {
//这里说明一定需要baseUrl。
throw new IllegalStateException("Base URL required.");
}
//这里判断如果没有callFactory的话,就会创建一个OkHttpClient()。
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//也是一样,如果没有callbackExecutor,就会设置成默认配置defaultCallbackExecutor。
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
//这里说明会把defaultCallAdapterFactories配置添加到List里面去
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 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);
converterFactories.addAll(platform.defaultConverterFactories());
//然后返回了一个Retrofit对象。
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
从build()
方法里可以看出,其实就是创建了一个OkHttpClient的对象,然后进行一系列的配置然后返回一个Retrofit的对象,这里是默认创建一个Okhttp的对象的,这也就代表你也可以外部创建一个Okhttp的对象然后进行传入,比如:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://wanandroid.com/wxarticle/chapters/json/")
.addConverterFactory(GsonConverterFactory.create())
//这里传入外部创建的okhttp对象
.client(new OkHttpClient())
.build();
创建网络接口的实例
//用Retrofit创建接口实例对象
ApiService apiService = retrofit.create(ApiService.class);
//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();
private final Object[] emptyArgs = new Object[0];
@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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
//这里用到了单例模式
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
然后经过Retrofit的create
创建源码,这是一个非常重要的方法,它是会返回一个泛型T,这里运用了Java的动态代理,也就是Proxy.newProxyInstance()
这里调用,然后调用了InvocationHandler()
的invoke()
方法,这里Invoke()
方法回向江method转换成ServiceMethod对象,然后传入到构造方法中,最后返回一个Call对象,这里面也用到了双重检查的单例模式,这就代表ServiceMethod只会被创建一次,然后我们重点来看看ServiceMethod是什么样的。
这里需要注意的是Retrofit2.5之前是通过构建者模式进行创建ServiceMethod的,2.5是使用ServiceMethod.parseAnnotations()
来进行创建.
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract T invoke(Object[] args);
}
这里你会发现它是一个抽象类,这就需要找它的子类的,它的子类是HttpServiceMethod,如下:
private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
CallAdapter<ResponseT, ReturnT> callAdapter,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
看到这里,其实也差不多明白了,这里创建了一个HttpServiceMethod对象,然后在Retrofit的create()
的方法中调用了invoke()
方法,返回了一个Call对象,就是我最初刚刚开始说的那个返回,主要是通过callAdapter.adapt()
返回,allAdapter.adapt()
方法就是将OkHttpCall对象转换成其他平台能用的Call对象,比如:RxJava。这里返回的是OkHttpCall的对象,该类是Retrofit中定义的,是对Okhttp中的Call对象的封装。
Retrofit的异步操作
@Override
public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
// 回调后 利用 MainThreadExecutor 中的 Handler 切换到主线程中去。
callbackExecutor.execute(new Runnable() {
@Override public void run() {
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(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
其实在异步操作这里主要是看它是怎么切换线程的,这里面有一个delegate,就是从这里进行网络请求的,它是一个OkHttpCall,具体的Call请求是交给okhttp来完成的,完成后通过主线程的Handler来切换到主线程中去,具体的网络请求,会写一篇okhttp的源码解析来继续。