现在的项目中用到了 Retrofit 用于网络请求,所以花了一些时间分析了它的源码,现在做一个简要的分析。
总体来看,Retrofit 使用了动态代理模式,它不是最终请求网络,真正请求网络的是 OkHttp. 这里,不做具体分析,我计划在下一篇再分析。
先看看它的整体流程
我们先看正常的使用 Retrofit, 然后再结合上图分析。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(sOkHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
这是正常的配置
1. 在 Retrofit.Buidler() 中的源码
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) {
// 根据 platform, 选择不同的 CallbackExecutor
// 这里是 platform 是 Android , 返回的是 MainThreadExecutor;
// MainThreadExecutor 类,内部是通过 Handler 将 Runnable post 回主线程执行
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// adaperFactories 是用来在存放 CallAdapterFactory, 例如使用 RxJavaCallAdapterFactory, 也会添加进来
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//defaultCallAdapterFactory 是 ExecutorCallAdapterFactory,其中 MainThreadExcutor 作为参数构造
adapterFactories.add(platform.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);
}
具体的分析看注释;
2. Retrofit.create()
在该方法中使用了动态代理模式,见 代理模式和动态代理模式,
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 动态代理, 返回一个 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);
}
// 默认是 false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy,
args);
}
// ServiceMethod 调用接口的方法,转变成一个 Http Call
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// serviceMethod.callAdapter 返回是 默认ExecutorCallAdapterFactory
// &ExecutorCallbackCall
// 如果添加了 RxJavaCallAdapter, 返回的是 RxJavaCallAdapter
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
3. ServiceMethod.build()
该方法主要做了三点
- 取出在 Retrofit.build 中的 CallAdapter, 例如上面配置的是 RxJavaCallAdapterFactory, 则得到的是 RxJavaCallAdapter;
- 取出 Retrofit.build 中的 responseConverter, 例如上面配置的是 GsonConverterFactory, 则得到 GsonResponseBodyConverter.
- 解析注解方法
public ServiceMethod build() {
// 创建 CallAdapter, 其实是返回 Retrofit 中的 callAdapter,
// ExecutorCallAdapterFactory$ExecutorCallbackCall
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// 返回 Retrofit.responseBodyConverter(...), 其实是从 converterFactories 中取出 ResponseBodyConverter
// 例如,如果配置了 GsonResponseBodyConverter, 则返回.
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
// 解析注解方法,
//@GET("group/{id}/users")
//Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
// 中的 @GET("group/{id}/users")
parseMethodAnnotation(annotation);
}
// 省略后面
....
}
Retrofit 的执行
call 的执行有同步方法和异步方法
同步 call.execute()
异步 call.enqueue(Callback callback);
这里以同步为例
1. OkHttpCall.execute
// 同步执行
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
// 省略
...
call = rawCall;
if (call == null) {
try {
// 创建 Call
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
// 发起请求,并解析返回结果
// 这里的 call 是 OkHttp 中的 RealCall
return parseResponse(call.execute());
}
2. OkHttpCall.createRawCall
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
// 返回的是 RealCall
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
3. OkHttCall.parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// 省略
....
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
// T 是想要的结果,例如 Call<List<Repo>> listRepos(@Path("user")
// String user); 中的 List<Repo>
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// 省略
...
}
}
3. ServiceMethod.toResponse
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
// responseConverter 是 Retrofit 中配置的 Conveter
return responseConverter.convert(body);
}
上面例子配置的 Conveter 是 GsonConverter, 所以,这里的 resonseConverter 是 GsonResponseConverter.
如果我们将 Http 返回的结果转换为想要的 Java 对象,就要实现 Converter 接口,同时也要实现 RequestConverter 和 ReponseConverter 具体的实现方式可参考源码中 Gson 转换方式。
至此, Retrofit 的源码基本分析完成。
注释的已经上传到 GitHub 上RetrofitAnnotions
个人觉得可以学到的很多知识点:
Retrofit 使用 Build 模式,其实很多开源库都用到了,具体可以看看《Effective Java》 中相关章节,里面有详细的介绍;
在 Retrofit 构造函数中 使用了 Collection.unmodifiableList(list) 方法,这样返回一个只可遍历的 List, 但不能进行修改的 List;
使用了动态代理模式;
检测一个类是否为 Interface , 调用 class.isInterface 即可。
utils.java 中
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
** 参考文章
这些文章都不错,推荐看看。**