引言
毫不掩饰的说,Retrofit 的源码是比较简单的,我也想做最简单的 Retrofit 解析,我认为源码解析是将晦涩难懂的源码和设计者的思想用简单的话语描述出来,这也是我做源码解析第一宗旨,You understand what I said.
本文摘要
- Retrofit 简介
- Retrofit 用法
- Retrofit 源码解析
Retrofit 简介
Retrofit 用法
本文基于 retrofit:2.3.0 版本
下面直接进入本文正题, Copy 官网的例子:
首先需要创建一个接口,接口中定义的每一个方法都代表着一个请求方法
//定义一个接口类
public interface GitHubService {
/**
* 定义一个请求方法,注解是 GET 代表这是一个 GET 请求
* "users/{user}/repos" 中 {user} 是替代符,被方法参数中 @Path 修饰的参 * 数所替代
* 返回值是 retrofit2.Call 类型
*/
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
下面要发出这个网络请求
//==================源码解析第一部分======= 创建 Retrofit ============
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
//==================源码解析第二部分======== 创建动态代理对象 ===========
GitHubService service = retrofit.create(GitHubService.class);
//==================源码解析第三部分======== 动态代理对象调用方法 ===========
Call<List<Repo>> repos = service.listRepos("octocat");
//==================源码解析第四部分======== 异步请求数据 ===========
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
如上,已经完成了 Retrofit 的一次网络请求调用。当初笔者从 OkHtttp/OkHttpUtils 转过来,内心一直不解,这也太麻烦了吧,还需要定义一个接口,接口上五花八门的注解又是什么意思?好多好多的疑问,我带着这个疑问开始了 Retrofit 源码解析。
带着问题看源码
- Retrofit 框架网络请求底层是依赖什么实现的?
- Retrofit 是怎么利用接口方法构建请求并发起的?
- Retrofit 中请求适配器 CallAdapter 的作用是什么?
- Retrofit 中转换器 Convert 的作用是什么?
Retrofit 源码解析
Retrofit 的源码还是比较易读的,下面分四个部分展开解析官网的例子,一步一步揭开 Retrofit 的面纱
创建 Retrofit
//==================源码解析第一部分======= 创建 Retrofit ============
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
让我们来看看上面的这段代码发生了什么?先介绍一下 Retrofit 这个类
Retrofit
首先看看其成员变量
public final class Retrofit {
//用于缓存解析的接口方法 ServiceMethod
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
/**
* 请求网络的OKHttp的工厂,默认是 OkHttpClient
* okhttp3.Call.Factory 是一个接口,只定义了一个方法
* =====Call newCall(Request request);========
*/
final okhttp3.Call.Factory callFactory;
//baseUrl,默认为 null
final HttpUrl baseUrl;
/**
* Converter.Factory 用于返回转换器对象 Converter
* 转换器对象 Converter 用于转换 ResponseBody/RequestBody 至
* 泛型规定的数据类型
* 默认会加入 retrofit2.BuiltInConverters
*/
final List<Converter.Factory> converterFactories;
/**
* CallAdapter.Factory 用于返回适配器对象 CallAdapter
* 适配器对象 CallAdapter 用于转换 Retrofit.Call 至
* 泛型规定的数据类型
* Android 平台默认会加入 retrofit2.ExecutorCallAdapterFactory
*/
final List<CallAdapter.Factory> adapterFactories;
//用于执行回调 Android 平台默认是
//retrofit2.Platform.Android.MainThreadExecutor
final @Nullable Executor callbackExecutor;
//是否需要立即解析接口中的方法,默认为 false
//设置为 true 会立即解析所有接口方法并放入缓存中
final boolean validateEagerly;
...
}
Retrofit 的成员变量就上面这么多,比较少,Happy~,第一步构建 Retrofit 的过程就是给这几个成员变量赋值的过程。
Retrofit.Builder
Retrofit.Builder 是 Retrofit 的静态内部类,用于构建 Retrofit,主要看 build()方法就行了
//=============== Retrofit.Builder # build() ============
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
//默认创建一个 OkHttpClient
callFactory = new OkHttpClient();
}
// Executor 接口只定义了一个方法
// void execute(Runnable var1);
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//在 Android 平台 platform 的实现类是 retrofit2.Platform.Android
//用于执行主线程回调,Android 平台默认是 MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
// 往适配器列表中传入平台默认的适配器 retrofit2.ExecutorCallAdapterFactory,并且将 callbackExecutor 传入
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
// 调用 Retrofit 构造方法,传入必要参数
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
经过上面的逻辑,Retrofit 就创建完成了,具备了一些基本的功能。示例代码中传入了 baseUrl 和一个 GsonConverterFactory(不传会报错),前者用于定义主机地址,后者用于转换 RequestBody/ResponseBody 。
创建动态代理对象
理解这一部分的前提是需要了解 Java 中的动态代理,可以参考此链接 轻松学,Java 中的代理模式及动态代理
//==================源码解析第二部分======== 创建动态代理对象 ===========
GitHubService service = retrofit.create(GitHubService.class);
点进去看看这个方法
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
//validateEagerly 为 true 立即解析所有接口方法并放入缓存
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);
}
//Android 平台为 false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//主要看下面这三行代码
//构建 ServiceMethod
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//构建 OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//接口方法定义的返回数据
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
简单总结:Retrofit#create(Class<T> service) 方法传入接口 Class 对象,方法的返回类型是该类的实例。实际上该类实例是通过动态代理生成的,每次该类实例调用方法时都会调用 Proxy.newProxyInstance()方法中的第三个参数 InvocationHandler # invoke()方法,在这个方法里执行真正的网络请求,解析接口方法生成请求,发送请求,返回响应转换的数据等一系列动作
动态代理对象调用方法
根据前面的解析,我们知道了动态代理对象每次调用方法都会触发 InvocationHandler#invoke()方法
在 invoke()方法中我们仅需要关注三行代码
//==================源码解析第三部分======== 动态代理对象调用方法 ===========
//构建 ServiceMethod
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//构建 OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//接口方法定义的返回数据
return serviceMethod.callAdapter.adapt(okHttpCall);
构建 ServiceMethod
ServiceMethod
这个类的作用是解析接口方法,将请求信息存储,交由 OkHttpCall 来调度生成 okhttp3.Call
下面还是先看看这个类的成员变量
final class ServiceMethod<R, T> {
//okhttp3.Call生产器,由 Retrofit 传入,默认为 OkHttpClient
final okhttp3.Call.Factory callFactory;
//适配器
final CallAdapter<R, T> callAdapter;
//主机地址,由 Retrofit 传入
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;
...
}
可以看出,这些变量大部分都是与请求相关的
下面开始构建过程
ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
//Retrofit 成员变量,前面介绍 Retrofit 时说过
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
//============ Retrofit # loadServiceMethod(Method method) ==========
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//从缓存中取出 ServiceMethod
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
//首次调用是走下面的逻辑
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//构建 ServiceMethod
result = new ServiceMethod.Builder<>(this, method).build();
//放入缓存
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod.Builder
ServiceMethod.Builder 是 ServiceMethod 的静态内部类,用于构建 ServiceMethod,主要看 build()方法就可以了
//================ ServiceMethod.Builder # build =========
public ServiceMethod build() {
//适配器对象,见下方分析1
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?");
}
//获得响应转换器,见下方分析4
responseConverter = createResponseConverter();
//遍历方法注解
for (Annotation annotation : methodAnnotations) {
//解析注解
parseMethodAnnotation(annotation);
}
//省略
...
//构建 ServiceMethod 对象
return new ServiceMethod<>(this);
}
构建 CallAdapter
//=======分析1===== ServiceMethod.Builder # createCallAdapter ========
private CallAdapter<T, R> createCallAdapter() {
//获取方法返回类型
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
//获取方法注解
Annotation[] annotations = method.getAnnotations();
try {
//接下来逻辑跳转到 Retrofit,看看 Retrofit 是怎么返回的
//见下方分析2
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);
}
}
//=======分析2===== 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) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//此处 skipPast 对象为空 , index() 方法返回 -1
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//从 Retrofit 的成员变量 adapterFactories 集合中取出 CallAdapter.Factory 对象,调用
//get()方法传入方法返回类型和方法注解,我们知道前面该集合默认传入的元素只有一个,就是
//ExecutorCallAdapterFactory,所以逻辑跳转到该类的get()方法,见下方分析3
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//省略了一些代码
...
}
//=======分析3===== ExecutorCallAdapterFactory ========该类不长且重要,所以整个类贴上来了
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
//Retrofit 构建时传入的主线程回调
final Executor callbackExecutor;
//构造方法,Retrofit 构造时调用
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
/**
* 主要看这个方法怎么返回 CallAdapter
*/
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//这里很关键,如果返回类型不是 retrofit2.Call 这个 ExecutorCallAdapterFactory 就没法工作了
//直接返回 null ,分析2处 Retrofit#nextCallAdapter 循环中返回结果为空,将继续遍历
//adapterFactories 的下一个元素
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ CallAdapter 实际返回就在这里了 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
//这个类就是接口方法里定义的返回类型的具体实现,待会我们再详细讲解这个类
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
}
构建 ResponseConverter
//=======分析4===== ServiceMethod.Builder # createResponseConverter ========
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
//接下来逻辑跳转到 Retrofit,看看 Retrofit 是怎么返回的
//见下方分析5
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
//=======分析5===== Retrofit # responseBodyConverter ========
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
//逻辑跳转下一个方法~
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//此处 skipPast 对象为空 , index() 方法返回 -1
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
//从 Retrofit 的成员变量 converterFactories 集合中取出 Converter.Factory 对象,调用
//responseBodyConverter()方法传入方法返回类型中定义的泛型类型(示例代码中是 List<Repo>)和方法注解,我们知道前面该集合
//传入的元素有两个,BuiltInConverters 和 GsonConverterFactory ,下标为0的时候是
//BuiltInConverters 所以逻辑跳转到该类的 responseBodyConverter()方法,见下方分析6
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
//省略一些代码,其实下面的代码是判断如果经过上方的遍历converter 仍然为空,就说明 Retrofit 配置的 ConverterFactory 无法为该接口方法提供ResponseBody/RequestBody转换,抛出异常~,从下面的逻辑梳理中我们可以知道,Retrofit 默认配置的 ConverterFactory 无法处理我们当前定义的接口请求方法响应类型为 List<Repo> 这样的数据类型
...
}
//=======分析6===== BuiltInConverters # responseBodyConverter ========
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {
//首先示例代码传入的响应类型 type 是 List<Repo>
//当前响应类型为 ResponseBody ,结果 false
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
//响应类型为 void ,结果 false
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
//此逻辑会返回 null,这个很重要,当一个 Converter.Factory 无法处理该类型转换的时候,返回 null
//上层调用分析5 处理链遍历将会去取下一个 Converter.Factory 来进行处理。所以下一个转换器是 //GsonConverterFactory,见分析7
return null;
}
//=======分析6===== GsonConverterFactory # responseBodyConverter ========
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ Converter 实际返回就在这里了 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
return new GsonResponseBodyConverter<>(gson, adapter);
}
经过上面的逻辑,ServiceMethod 就构建完成了,还是老一套,为了给 ServiceMethod 中相关的成员变量赋值。我们知道了,callAdapter 的实现是 ExecutorCallbackCall,responseConverter 的实现是 GsonResponseBodyConverter。这两个类对下面分析的流程至关重要哦~,同时 ServiceMethod 通过解析接口请求方法,已经知道了该接口方法定义的请求所需要的所有参数。
构建 OkHttpCall
介绍 OkHttpCall 之前先介绍 retrofit2.Call
retrofit2.Call
是 Retrofit 用于发起请求的接口规则,类似于 okhttp3.Call
package retrofit2;
import java.io.IOException;
import okhttp3.Request;
public interface Call<T> extends Cloneable {
//同步执行请求
Response<T> execute() throws IOException;
//异步执行请求,callback 用于回调
void enqueue(Callback<T> callback);
//是否执行过
boolean isExecuted();
//取消请求
void cancel();
//是否取消了
boolean isCanceled();
//克隆一条请求
Call<T> clone();
//获取原始的request
Request request();
}
OkHttpCall
OkHttpCall 是 Call 的实现类,里面封装了 OkHttp 中原生的 Call。OkHttpCall 这个类里实现了 execute()和 enqueue()等方法,其实是调用了 OkHttp 原生 Call 的方法。
下面开始 OkHttpCall 构建过程
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;
private volatile boolean canceled;
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this")
private @Nullable Throwable creationFailure; // Either a RuntimeException or IOException.
@GuardedBy("this")
private boolean executed;
/**
* 构造方法
* @param serviceMethod 解析接口方法类
* @param args 接口方法参数
*/
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@SuppressWarnings("CloneDoesntCallSuperClone") // We are a final type & this saves clearing state.
@Override public OkHttpCall<T> clone() {
return new OkHttpCall<>(serviceMethod, args);
}
@Override public synchronized Request request() {
okhttp3.Call call = rawCall;
if (call != null) {
return call.request();
}
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw new RuntimeException("Unable to create request.", creationFailure);
} else {
throw (RuntimeException) creationFailure;
}
}
try {
return (rawCall = createRawCall()).request();
} catch (RuntimeException e) {
creationFailure = e;
throw e;
} catch (IOException e) {
creationFailure = e;
throw new RuntimeException("Unable to create request.", e);
}
}
/**
* 具体分析这个方法
* 异步请求方法
* @param callback 异步回调
*/
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
//这里出现了 OkHttp 的 Call 类型变量
//往下看就明白了,这里调用了 okhttp3.Call.enqueue(okhttp3.Callback)方法
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//构建 okhttp3.Call
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//调用 okHttp3.Call 的方法进行异步请求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
@Override public synchronized boolean isExecuted() {
return executed;
}
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
/**
* 重点关注这个方法
* 构建 okhttp3.Call
*/
private okhttp3.Call createRawCall() throws IOException {
//见下方分析1,将从接口请求方法中解析得出的请求信息封装成 Request 对象
Request request = serviceMethod.toRequest(args);
//serviceMethod.callFactory 其实是 Retrofit 构建时默认创建的 OkHttpClient 对象
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
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;
}
}
public void cancel() {
canceled = true;
okhttp3.Call call;
synchronized (this) {
call = rawCall;
}
if (call != null) {
call.cancel();
}
}
@Override public boolean isCanceled() {
if (canceled) {
return true;
}
synchronized (this) {
return rawCall != null && rawCall.isCanceled();
}
}
static final class NoContentResponseBody extends ResponseBody {
private final MediaType contentType;
private final long contentLength;
NoContentResponseBody(MediaType contentType, long contentLength) {
this.contentType = contentType;
this.contentLength = contentLength;
}
@Override public MediaType contentType() {
return contentType;
}
@Override public long contentLength() {
return contentLength;
}
@Override public BufferedSource source() {
throw new IllegalStateException("Cannot read raw response body of a converted body.");
}
}
static final class ExceptionCatchingRequestBody extends ResponseBody {
private final ResponseBody delegate;
IOException thrownException;
ExceptionCatchingRequestBody(ResponseBody delegate) {
this.delegate = delegate;
}
@Override public MediaType contentType() {
return delegate.contentType();
}
@Override public long contentLength() {
return delegate.contentLength();
}
@Override public BufferedSource source() {
return Okio.buffer(new ForwardingSource(delegate.source()) {
@Override public long read(Buffer sink, long byteCount) throws IOException {
try {
return super.read(sink, byteCount);
} catch (IOException e) {
thrownException = e;
throw e;
}
}
});
}
@Override public void close() {
delegate.close();
}
void throwIfCaught() throws IOException {
if (thrownException != null) {
throw thrownException;
}
}
}
}
//=========分析1=============== ServiceMethod # toRequest ============
Request toRequest(@Nullable Object... args) throws IOException {
//将 ServiceMethod 中跟请求相关的成员变量传入 RequestBuilder 构造函数中
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
上面 OkHttpCall 这个类的所有代码,有点长但是很容易理解,可以看到类中没有很多需要赋值的变量,再看看类中的方法,OkHttpCall 实现了 retrofit2.Call 接口,挑一个方法的具体实现来看,比如 enqueue(final Callback<T> callback) 方法,逻辑也比较简单,实际上就是通过 ServiceMethod#toRequest 方法构建一个 Request 对象,交给 serviceMethod.callFactory.newCall(request) 方法构建一个 okhttp3.Call 对象并执行其异步请求方法。同理可以分析execute()方法等,看完就明白了,Retrofit 的底层默认是依靠 OkHttp 来发送网络请求的~
接口方法定义的返回数据
return serviceMethod.callAdapter.adapt(okHttpCall);
这根据我们上面的分析,我们已经可以知道这行代码返回的对象其实就是 ExecutorCallbackCall
异步请求数据
//==================源码解析第四部分======== 异步请求数据 ===========
Call<List<Repo>> repos = service.listRepos("octocat");
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
从上面的分析已经知道了 Call<List<Repo>> repos 的真正实现其实是 ExecutorCallbackCall,接下来只要看 ExecutorCallbackCall 的 enqueue(CallBack)方法
//======= ExecutorCallAdapterFactory.ExecutorCallbackCall # enqueue(Callback) ============
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
//delegate 是 ExecutorCallbackCall 构建时传入的 OkHttpCall 对象
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
//callbackExecutor 是构建时传入的主线程回调
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);
}
});
}
});
}
ExecutorCallbackCall # enqueue 方法逻辑也比较容易理解,调用 retrofit2.OkHttpCall 对象的 enqueue 方法,并使用构建时传入的 callbackExecutor 来做主线程回调请求结果。这样就分析完了例子中整个的请求过程。
总结
回到最初的问题
Retrofit 框架网络请求底层是依赖什么实现的?
Retrofit 中负责发起请求的是 retrofit2.OkHttpCall 对象,而 retrofit2.OkHttpCall 又是依赖于 okHttp3.Call 对象发起请求的,okHttp3.Call 对象的构建依赖于 Retrofit 的成员变量 okhttp3.Call.Factory callFactory。所以很明显,Retrofit 网络请求底层是依赖 OkHttp 的。Retrofit 是怎么利用接口方法构建请求并发起的?
Retrofit 通过动态代理和注解解析接口方法,判断请求方法类型、请求的地址、返回数据类型等,将接口方法封装成 ServiceMethod,交给 retrofit2.OkHttpCall 进行调度生成 okhttp3.Request 对象,再创建 okhttp3.Call 来发起请求。-
Retrofit 中请求适配器 CallAdapter 的作用是什么?
适配器的作用是将 retrofit2.Call 转换为接口方法定义的返回值类型 。首先需要明确,Retrofit 是依赖 OkHttp 发起请求的,并且将 okhttp3.Call 封装了一层变成 retrofit2.Call,用 Retrofit 进行网络请求默认的调度对象就是 retrofit2.Call 的默认实现类 retrofit2.OkHttpCall。ServiceMethod 构建的时候会根据接口方法返回值类型从 Retrofit 的 CallAdapterFactory 列表中选取能够转换的适配器,适配器真正作用的地方在源码解析第三部分的最后一点:return serviceMethod.callAdapter.adapt(okHttpCall);
按照官网的例子分析会比较好理解,实际上是将 retrofit2.OkHttpCall 转化为了 ExecutorCallbackCall。这也是当接口方法返回值类型为 retrofit2.Call 时 Retrofit 的默认返回类型,里面封装了主线程回调。相当于给 OkHttp.Call 加了个主线程的 Handler。
另外,当 Retrofit 与 Rxjava2 结合,构建 Retrofit 时可以传入 RxJava2CallAdapterFactory,能够将 retrofit2.Call 转换为 Observable 类型,与 Rxjava2 搭配起来使用就更方便了 。 Retrofit 中转换器 Convert 的作用是什么?
转换器的作用是将 ResponseBody 转换为某种数据,或者是将某种数据转换为 RequestBody。
按照官网的例子分析,返回值是 Call<List<Repo>> ,Retrofit 默认的转换器 BuiltInConverters 是无法完成这个工作的。我们看到 ServiceMethod 在构建 Converter<ResponseBody, T> responseConverter 时,BuiltInConverters 无法完成该变量的初始化将直接返回 null ,逻辑接着来到 GsonConverterFactory ,这个转换器工厂可以处理,返回的是 GsonResponseBodyConverter,那么 Converter<ResponseBody, T> responseConverter 就赋值完毕了,什么时候调用呢?注意看 retrofit2.OkHttpCall 在执行同步 execute()或异步 enqueue(final Callback<T> callback) 调用时,在获取到 okhttp3.Response 之后都会调用 OkHttpCall.parseResponse(okhttp3.Response rawResponse)方法,在这个方法里最重要的是主动调用了 ServiceMethod.toResponse(ResponseBody body)方法
//================= ServiceMethod # toResponse =================
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
这里我们看到直接调用了convert(ResponseBody body)方法,下面贴出 GsonResponseBodyConverter 源码
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
//通过 Gson 将 ResponseBody 转化为 List<Repo>
//如果熟悉泛型的应用,这个 T 其实就是 List<Repo>
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
通过上面的代码,我们就可以得出 Convert 的作用。其实是 Retrofit 通过 Okhttp.Call 获得响应后对 ResponseBody 进行转化,直接变成用户需要的数据这一过程的统一封装。那么 Convert 的另一作用,转化 RequestBody 则发生在 ServiceMethod # toRequest 方法中,类似的处理逻辑。
阅读感悟
Retrofit 通过接口定义请求的方式,很简洁,开发者只需要将请求一个一个的定义好,剩下的就交给Retrofit了,对于请求的复用,统一管理都是很方便的。另外源码中涉及的动态代理和注解这些 Java 的高级特性的应用也让我收获不少,关于设计模式比较明显的是适配器模式、代理模式、外观模式和装饰模式。好,读完以后真的畅快淋漓啊,下一篇我想写的是关于 Retrofit 注解的使用示例~
如果您看到文中有错误的地方欢迎在评论区指出,我会及时修改。