Retrofit2.0源码解析
引用
Retrofit是Square生产的一款用于网络请求的框架,遵循RestApi风格,以其简单的网络配置与自定义设置,支持RxJava,自定义数据转换器等,Github上的start数已经有将近3w,而且目前一直在维护,内部网络请求采用okhttp来进行网络访问,这一系列的特性使其成为网络请求框架的新宠儿
既然Retrofit如此火爆,那么自然是因为其良好的设计架构,完美的项目解耦,其实Retrofit最大的优点就是他使用了多种设计模式来进行解耦,比如 CallAdapterFactory
,ConvertAdapterFactory
来根据用户传入的不同类型的适配器对数据进行梳理,用户没必要关心数据的变化,一次配置,终身享用。好了,还是直接来根据代码探究Retrofit的优美,本篇文章是基于Retrofit2.0版本来进行代码跟踪,好了,开车。
- 创建一个全局Retrofit实体类
Retrofit retrofit = new Retrofit.Builder()// 构建者模式填充参数
.baseUrl("http://127.0.0.1:8080") // 必填 http的主机名+端口号 *以/结尾
.client(new OkHttpClient()) // 选填,可定制OkHttpClient 比如添加相应的拦截器等
.addConverterFactory(GsonConverterFactory.create()) // 添加response中body的数据转换工厂
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加 call(okhttp中请求的执行体) 的转换工厂,这里就转换成了Observable
.build();
以上就是Retrofit实体对象的创建,一般创建为全局单例,个人喜欢放在静态代码块中,上面提到的OkHttpClient
一般都是自己定制,创建拦截器,添加Token到Headers等,OkHttpClient
也最好写成全局唯一,因为每一个OkHttpClient
内部维护的网络请求线程池以及connnection
连接池都是维护在一个OkHttpClient
实体对象中的,一旦每次请求去创建就会丧失OkHttpClient
的性能,OkHttp
的源码解析可以看我的上篇OkHttp源码解析
接下来我们看一下Retrofit的源码,看一下Retrofit的都有哪些参数,以及我们传递的这些参数用来做什么呢?
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>(); // 由于缓存每个api生成的方法
final okhttp3.Call.Factory callFactory; // 执行器工厂 这里代表OkHttpClient
final HttpUrl baseUrl; // 主机名+端口号
final List<Converter.Factory> converterFactories; // 数据转换器工厂集合
final List<CallAdapter.Factory> adapterFactories; // 执行器适配工厂集合
final @Nullable Executor callbackExecutor; // 回调执行器
- 创建基于注解的RestApi接口:
public interface ApiService {
// retrofit的post请求
@POST("/app/v1/user/login")
Call<HttpResult<UserVo>> loginPost(@Body Map<String, Object> params);
}
所有的api都是以注解的形式卸载这个接口中,该接口用来生成上面提到的缓存的MethodServcie;
- 构建Api的生产接口
apiService = retrofit.create(ApiService.class);
- API的调用
Map<String,Object> map = new HashMap<>();
map.put("name","lu");
map.put("password","123");
apiService.loginPost(map).enqueue(new Callback<HttpResult<UserVo>>() {
@Override
public void onResponse(Call<HttpResult<UserVo>> call, Response<HttpResult<UserVo>> response) {
Log.d(TAG, "onResponse: "+success);
}
@Override
public void onFailure(Call<HttpResult<UserVo>> call, Throwable t) {
Log.d(TAG, "onFailure: "+fail);
}
});
以上就是一整套Retrofit的网络请求。
- 分析Retrofit源码创建过程:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service); // 验证该接口的合法性
if (validateEagerly) {
eagerlyValidateMethods(service); // 1.1
}
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);// 1.2
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//1.3
return serviceMethod.callAdapter.adapt(okHttpCall);//1.4
}
});
}
- 1.1 该段代码会在Retrofit第一次cretae的时候调用,点进去:
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get(); // 获取当前的PlatForm #1.1.1
// 遍历接口中所有Method
for (Method method : service.getDeclaredMethods()) {
//判断是不是default方法,jdk7以后接口中可以编写方法的实现,但是必须在方法前面设置一个关键字`default'
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method); #1.1.2
}
}
}
-
1.1.1 获取当前Platform(平台),该类包含两个实现类:
Platform 实现类
因为Retrofit
这个支持Android同时也支持Java所以会根据Class的包名判断是当前平台环境:
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();
}
而我们只来卡一下Android这个Platform的实现类,这个类总共十几行:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
// 构建一个用来将响应事件发送到Main线程
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
// 返回一个默认的Call(执行器)的适配器工厂,就是用来将执行结果转换成你想要的返回对象,比如,你想要Observer<Object> 等
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
- 1.1.2 加载接口中的非default方法,构建一个ServiceMethod对象,以Method为Key,该对象队value添加到到文章开始讲的方法集合缓存起来,:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 传入Retrofit实例和Method到MethodBuild=对象构建一个ServiceMethod,该对象将会包含Retrofit所有数据,以后就是又来对象完成数据请求以及封装
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
好了,再来看一下这个方法的动态代理里面的东西:
(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)) {//如果该方法是声明为default,则正常调用该方法,
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);// 1.2
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);//1.3
return serviceMethod.callAdapter.adapt(okHttpCall);//1.4
}
});
-
1.2 从缓存ServiceMethod的方法的集合中根据Method获取该ServiceMethod实例对象。
-
1.3 根据Method和参数创建一个
OkHttpCall
这个和OkHttp中的Call是相同的功能,如果不太清楚查看上篇OkHttp源码分析了解Call的执行流程,其实就是代表一个请求的执行对象。 -
1.4 前面提到ServiceMethod在构建的时候传入了this(retrofit实例)所有持有Retrofit的所有实例成员,这里调用
callAdapter
实例来将call
对象传入,使用构造Retrofit时传入的CallAdapter.Factory
对象将该Call对象转换成factory
所需要的返回类型,我们看一下这个CallAdapter.Factory
接口:
public interface CallAdapter<R, T> {
T adapt(Call<R> call);
abstract class Factory {
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
其实就是讲CallAdapter< R >
转换成CallAdapter< T >
,接下来看一下实现该接口的都是那些:

上面在讲Platform说过,默认的CallAdapterFactory
就是 ExectuorCallAdapterFactory
,我们只关心他的adapter
方法:
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
创建了一个ExecutorCallbackCall
其中第一个参数其实就是Android那个Platform中的MainThreadExecutor
(持有有个主线程的Handler,发送响应是事件到主线程),那来看一下这个类到底做了什么:
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor; // 回调的Executor
final Call<T> delegate; // 代理Call 真正的执行Call
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
// 发送同步请求
@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) {
// 发送响应到主线程
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);
}
});
}
});
}
// 判断该Call是否已经执行
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
// 发送同步请求
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
// 取消该call 就是在okhttp的call池中移除,具体参看我的上篇okhttp源码分析
@Override public void cancel() {
delegate.cancel();
}
// 判断该Call是否已经取消掉了
@Override public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
走到这里,可以继续点进去,其实真正执行http请求的还是OkHttp。
再看一下Retrofit
创建的时候添加ConvertFatory
,这个主要就是用来进行响应结果的数据类型转换,看一下GsonConvertFactory
:
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
没多少代码,其实就是利用Gson将response转换成实体对象,自己也可以写一个,只要实现Converter<F, T>
这个接口,Retrofit不仅仅只支持gson,还支持其他许多json解析库。以下版本号需要与retrofit版本号保持一致,并且以retrofit官网给出的版本号为准。
- Gson: compile 'com.squareup.retrofit2:converter-gson:2.0.1'
- Jackson: compile 'com.squareup.retrofit2:converter-jackson:2.0.1'
- Moshi: compile 'com.squareup.retrofit2:converter-moshi:2.0.1'
- Protobuf: compile 'com.squareup.retrofit2:converter-protobuf:2.0.1'
- Wire: compile 'com.squareup.retrofit2:converter-wire:2.0.1'
- Simple XML: compile 'com.squareup.retrofit2:converter-simplexml:2.0.1'
- Scalars (primitives, boxed, and String): compile 'com.squareup.retrofit2:converter-scalars:2.0.1'
Retrofit这个框架包含了好多设计模式在里面,比如外观、工厂、适配器、构建者、等等,个人只是懂一点皮毛,个人理解而已。