本文基于Retrofit 2.3.0
,OkHttp 3.8.0
进行分析。
使用示例
public class GitHubRetrofit {
private Retrofit retrofit;
public static GitHubRetrofit newInstance() {
return new GitHubRetrofit();
}
private GitHubRetrofit() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.build();
retrofit = new Retrofit.Builder()
.baseUrl("http://www.github.com/")
.client(okHttpClient)
.build();
}
public Call<ResponseBody> createPop() {
Pop pop = retrofit.create(Pop.class);
return pop.robots();
}
public interface Pop {
@GET("robots.txt")
Call<ResponseBody> robots();
}
}
Response<ResponseBody> execute = GitHubRetrofit.newInstance().createPop().execute();
以上是Retrofit的简单使用示例,下面从以上代码为入口分析其内部实现。
源码分析
Retrofit实例化
先来分析下Retrofit
的实例化过程
retrofit = new Retrofit.Builder()
.baseUrl("http://www.github.com/")
.client(okHttpClient)
.build();
很明显Retrofit
实例的创建采用了建造者模式。
通过baseUrl
方法设置网络请求的base url。
client
方法接收OkHttpClient
实例,整个网路请求是由Retrofit
和OkHttp
结合完成的,关于OkHttp
的内容本文不做深入讲解。
接下来看Builder
类的build
方法,以下是代码实现
public Retrofit build() {
...
// 检查是否设置OkHttp实例,如果没有,提供默认实现
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 检查是否设置callback executor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// 使用集合保存所有通过addCallAdapterFactory方法添加的CallAdapter.Factory实现类实例,并保存默认实现
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
// 使用集合保存所以通过addConverterFactory方法添加的Converter.Factory实现类实例
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
Retrofit
中的CallAdapter.Factory
,Converter.Factory
成员变量都采用了面向接口编程的方式,极大的提高了程序的可扩展性。
比如CallAdapter.Factory
,框架提供了默认实现类ExecutorCallAdapterFactory
来支持Call
返回类型。如果想要支持Observable
为返回类型,只需要调用addCallAdapterFactory(RxJavaCallAdapterFactory.create())
。
platform.defaultCallbackExecutor(),返回的是MainThreadExecutor实例,内部使用Handler实现
platform.defaultCallAdapterFactory(),返回的是ExecutorCallAdapterFactory实例
Retrofit创建接口实现类及实例
Retrofit.create
GitHubRetrofit.newInstance().createPop().execute();
public Call<ResponseBody> createPop() {
Pop pop = retrofit.create(Pop.class);
return pop.robots();
}
以上代码表明Retrofit
的create
方法创建并返回了一个Pop
接口的实例
接下来分析create
方法,源码如下
public <T> T create(final Class<T> service) {
// 校验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.callAdapter.adapt(okHttpCall);
}
});
}
create
方法使用了Java
的动态代理技术来创建接口类的实现类及实例的创建。
使用动态代理创建的接口实例,在调用接口方法时都会由InvocationHandler
的invoke
来处理。
GitHubRetrofit.newInstance().createPop().execute();
public Call<ResponseBody> createPop() {
Pop pop = retrofit.create(Pop.class);
return pop.robots();
}
也就是说pop.robots()
执行最终会调用到invoke方法。
invoke
方法中的主要功能在于ServiceMethod
的loadServiceMethod
方法和serviceMethod
中callAdapter
实例的adapt
方法的执行。
ServiceMethod.loadServiceMethod
先来看loadServiceMethod
方法,源码如下
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 如果有缓存,直接返回
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 可能出现同时调用多个网络请求的场景,需要保证serviceMethodCache线程安全
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
以上代码主要完成两件事,一是创建ServiceMethod
实例,二是对ServiceMethod
实例进行缓存。
重点关注ServiceMethod
的实例化过程,很明显又是采用的建造者模式。
直接来看build
方法,源码如下
public ServiceMethod build() {
// 创建CallAdapter实例
callAdapter = createCallAdapter();
// 使用callAdapter获取ServiceMethod的返回类型
responseType = callAdapter.responseType();
// 创建response转换器
responseConverter = createResponseConverter();
...
for (Annotation annotation : methodAnnotations) {
// 解析方法中标注的注解类型,GET,POST等
parseMethodAnnotation(annotation);
}
...
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
...
// 解析接口方法中传入的参数
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
...
return new ServiceMethod<>(this);
}
以下是ServiceMethod
的成员变量,结合build
方法中的代码不难看出,ServiceMethod
的build
方法主要将method
中的数据解析为网络请求相关数据。
final class ServiceMethod<R, T> {
...
final okhttp3.Call.Factory callFactory;
final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
}
CallAdapter.adapt
接下来分析invoke
中最后一行代码return serviceMethod.callAdapter.adapt(okHttpCall);
ServiceMethod
中的callAdapter
是在ServiceMethod.build
方法中调用ServiceMethod.createCallAdapter
方法被创建的。
以下是ServiceMethod.createCallAdapter
的实现
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
...
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
Retrofit.callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}
从上面的代码可以看出,ServiceMethod
中的CallAdapter
来自Retrofit
,也就是调用Retrofit.Builder.addCallAdapterFactory
添加的工厂类创建的CallAdapter
实例(如果没有调用addCallAdapterFactory
会默认使用ExecutorCallAdapterFactory
)。
Retrofit
会遍历adapterFactories
集合,集合中的CallAdapter.Factory
实现类验证传入的returnType
,如果满足验证条件则返回CallAdapter
实例,如果不满足则返回null
。
以下是RxJavaCallAdapterFactory
及ExecutorCallAdapterFactory
的get方法。
RxJavaCallAdapterFactory
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
// 判断返回类型是否 为 Observable
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
if (isCompletable) {
return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
...
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
...
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
...
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
false);
}
ExecutorCallAdapterFactory
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 判断返回类型是否 为 Call
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
接下来看CallAdapter
的adapt
方法,这里以ExecutorCallAdapterFactory
为例来分析。从上面的代码可以发现,ExecutorCallAdapterFactory
直接返回了一个匿名内部类CallAdapter
实例,它的adapt
方法中返回了一个Call
接口实现类ExecutorCallbackCall
的实例。
GitHubRetrofit.newInstance().createPop().execute();
public Call<ResponseBody> createPop() {
Pop pop = retrofit.create(Pop.class);
return pop.robots();
}
可以看到 pop.robots()
方法返回了一个Call
接口实例,也就是ExecutorCallbackCall
实例。
调用接口方法创建网络请求
GitHubRetrofit.newInstance().createPop().execute();
接下来分析excute()
方法,从以上分析中了解到createPop()
方法返回的是ExecutorCallbackCall
实例
下面是ExecutorCallbackCall
的源码
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
...
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
...
}
可以看出实际是调用了delegate
的execute
方法,这里的delegate
是一个OkHttpCall
实例,是在invoke
中最后一行代码return serviceMethod.callAdapter.adapt(okHttpCall);
中传入的。
以下是OkHttpCall
中execute
方法的源码实现
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
...
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
...
return parseResponse(call.execute());
}
以上代码中主要做了以下三件事
- 创建
Call
实例 - 调用
Call
的execute
方法 - 解析响应数据
OkHttpCall.createRawCall
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
可以看到是Call
实例是由ServiceMethod
创建的,分析ServiceMethod.loadServiceMethod
方法了解到ServiceMethod
类保存了网络请求相关的数据,所以Call实例的创建也应该由其来完成。
ServiceMethod
的callFactory
是一个OkHttp
实例,可以在创建Retrofit
实例时传入。
RealCall.execute
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
从以上代码可以看出,RealCall
是将其传给OkHttpClient
进行分发执行。
OkHttpCall.parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
以上为解析并生成Response
实例的过程,主要做了三件事
- 异常处理
- 根据响Http Code对数据进行相应处理
- 使用
ServiceMethod
的toResponse
方法将数据转换为指定格式
ServiceMethod.toResponse
的内容是由Retrofit
中的Converter.Factory
实现类创建出的实例来完成。
相关设计模式
建造者模式
Retrofit.Builder
ServiceMethod.Builder
外观模式
ServiceMethod.oResponse(ResponseBody body)
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
框架提供了以下几种Coverter.Factory实现
- GsonConverterFactory
- GuavaOptionalConverterFactory
- JacksonConverterFactory
- Java8OptionalConverterFactory
- MoshiConverterFactory
- ProtoConverterFactory
- ScalarRequestBodyConverter
- SimpleXmlConverterFactory
- WireConverterFactory
更多文章点击这里