一、概述
作为 Android 开发者的我们都知道,当我们写一个网络请求的时候,需要写很多代码,很不方便,在这样的背景下,Retrofit 就应运而生了,Retrofit 是当下比较热门的一个框架,如果你不了解 Retrofit 的用法,请点击这里,那本文主要讲解的就是我们的 Retrofit 的原理,在了解他的原理之前,你首先要了解的就是动态代理,Retrofit 之所以简洁,是因为他在运行时帮我们生成代码,让我们少写了很多代码,当他想在运行时插入代码的时候,那么就用到了动态代理,如果不了解动态代理的,请点击这里,那下面我们就进入我们本篇的正文
二、Retrofit 中用到的 http 相关内容讲解
在我们了解 Retrofit 之前,我先说一下我们用到的 http 的知识,首先我们要知道,我们的 http 请求可以把数据放到三个位置:
1、放到 url 的尾部,这种方式对应我们的 Retrofit 的 @Query 注解。
2、放到 Form 表单中,那这种方式对应我们的 @Field 注解,我们要注意的是,我们的 Form 表单中不支持放入文件。
3、放到我们的 body 中,这种方式就比较灵活了,对应我们的 Retrofit 的 @Part 注解,这种方式传递参数我们需要把参数转换成 RequestBody。
注意:我们的第二种和第三种只能用一种,要么用 Form 表单的形式上传,要么用 Multipart ,不过这两种方式都可以与第一种相结合(需要服务端的支持)。
基本的内容我们都了解的差不多了,那下面我们就进入正题,分析我们的一个请求的流程到底是什么样的。
三、源码解析
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("www.ehuodi.com")
.client(new OkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build();
EhuodiApi ehuodiApi = retrofit.create(EhuodiApi.class);
Call<String> call = ehuodiApi.selectPreLoading();
3、发送请求:
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
public final class Retrofit {
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();//这个主要是缓存的作用,缓存我们生成的代理方法,这也是第二次请求速度快的原因
private final okhttp3.Call.Factory callFactory; //网络请求工厂,生成 call 的默认用的是 okhttp 的call
private final HttpUrl baseUrl; //网络请求的 baseUrl,也就是我们第一步指定的 url
private final List<Converter.Factory> converterFactories; //我们解析器的集合,会存我们手动添加和系统默认的解析器
private final List<CallAdapter.Factory> adapterFactories; //网络请求的适配工厂,主要是适配平台的
private final Executor callbackExecutor; //我们回调执行的线程池
private final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
public Builder() {
this(Platform.get());
}
②、通过调用 findPlatform 去选择平台
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) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
④、在这个方法中我们可以看到,他创建了一个线程池,一个运行在主线程中的线程池,也就是这个线程池的作用导致我们可以在 callback 中处理 UI。
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
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);
}
}
}
⑤、
Builder(Platform platform) {
this.platform = platform;
// 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());
}
产物:通过 new Request.builder 我们创造出来的东西是一个 Platform 类,在这个类中我们可以通过方法获取一个 ExectorCallAdapterFactory,那这个类的具体内容我们后面再说,然后在我们的解析器中加入了一个 BuiltInConverters 解析器,这是一个默认的解析器。我们这一部分的分析只需要知道我们生成了一个 PlatForm 对象并加入了一个默认的解析器就可以了。
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
我们可以看到,这部其实很简单,只是给我们的 baseUrl 去进行赋值,而且还做了一些判断。
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory; //如果没有指定 call.factory ,那么默认用 okhttpclient
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor; //这个是我们回调线程池 ①
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); //②
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); //用创建的变量构造 Retrofit
}
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
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();
@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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method); //①
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); //②
return serviceMethod.callAdapter.adapt(okHttpCall); //③
}
});
}
我们都知道动态代理生成的代理类,在调用被代理的接口中的方法的时候都会执行 InvlcationHandler 中的 invoke 方法,那重点也就到了我们的 invoke 方法啊了,这个方法中首先是做了一些判断,重点来了,判断之后显示通过 loadServiceMethod 生成代理方法,然后通过代理方法生成 OkhttpCall ,最后通过 okhttpCall 返回了一个代理对象
public ServiceMethod build() {
callAdapter = createCallAdapter();
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器 -->关注点1
responseType = callAdapter.responseType();
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型
responseConverter = createResponseConverter();
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器 -->关注点3
// 构造 HTTP 请求时,我们传递的参数都是String
// Retrofit 类提供 converter把传递的参数都转化为 String
// 其余类型的参数都利用 Converter.Factory 的stringConverter 进行转换
// @Body 和 @Part 类型的参数利用Converter.Factory 提供的 requestBodyConverter 进行转换
// 这三种 converter 都是通过“询问”工厂列表进行提供,而工厂列表我们可以在构造 Retrofit 对象时进行添加。
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 解析网络请求接口中方法的注解
// 主要是解析获取Http请求的方法
// 注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded
// 处理主要是调用方法 parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) ServiceMethod中的httpMethod、hasBody、relativeUrl、relativeUrlParamNames域进行赋值
int parameterCount = parameterAnnotationsArray.length;
// 获取当前方法的参数数量
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
// 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
// 该对象的创建过程就是对方法参数中注解进行解析
// 这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
<-- 总结 -->
// 1. 根据返回值类型和方法标注从Retrofit对象的的网络请求适配器工厂集合和内容转换器工厂集合中分别获取到该方法对应的网络请求适配器和Response内容转换器;
// 2. 根据方法的标注对ServiceMethod的域进行赋值
// 3. 最后为每个方法的参数的标注进行解析,获得一个ParameterHandler<?>对象
// 该对象保存有一个Request内容转换器——根据参数的类型从Retrofit的内容转换器工厂集合中获取一个Request内容转换器或者一个String内容转换器。
}
<-- 关注点1:createCallAdapter() -->
private CallAdapter<?> createCallAdapter() {
// 获取网络请求接口里方法的返回值类型
Type returnType = method.getGenericReturnType();
// 获取网络请求接口接口里的注解
// 此处使用的是@Get
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.callAdapter(returnType, annotations);
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器
// 下面会详细说明retrofit.callAdapter() -- >关注点2
}
...
<-- 关注点2:retrofit.callAdapter() -->
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
// 创建 CallAdapter 如下
// 遍历 CallAdapter.Factory 集合寻找合适的工厂(该工厂集合在第一步构造 Retrofit 对象时进行添加(第一步时已经说明))
// 如果最终没有工厂提供需要的 CallAdapter,将抛出异常
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
<-- 关注点3:createResponseConverter() -->
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
// responseConverter 还是由 Retrofit 类提供 -->关注点4
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) {
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
<-- 关注点4:responseBodyConverter() -->
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
// 获取Converter 过程:(和获取 callAdapter 基本一致)
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
// 遍历 Converter.Factory 集合并寻找合适的工厂(该工厂集合在构造 Retrofit 对象时进行添加(第一步时已经说明))
// 由于构造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter
// Retrofit - Converters 还提供了 JSON,XML,ProtoBuf 等类型数据的转换功能。
// 继续看responseBodyConverter() -->关注点5
}
<-- 关注点5:responseBodyConverter() -->
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
// 根据目标类型,利用 Gson#getAdapter 获取相应的 adapter
return new GsonResponseBodyConverter<>(gson, adapter);
}
// 做数据转换时调用 Gson 的 API 即可。
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 {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
可以看到只是简单的赋值,那我们的 serviceMethod 就是我们的 okhttpCall 的成员变量了
return serviceMethod.callAdapter.adapt(okHttpCall);
public ServiceMethod build() {
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?");
}
从上面的代码中可以看出,这是调用了 callAdapter 的 adapt 方法,那我们从上节知道我们的 callAdapter 是通过 createCallAdapter 获取的,那从上节我们也知道,我们的 callAdapter 是通过 Retrofit 获取的,那我们都知道我们 Retrofit 的 callAdapter 是 Android 平台的 ExecutorCallAdapterFactory,那我们只需要看一下 ExecutorCallAdapterFactory 中的 adapt 做了什么就可以了,看代码:
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
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 void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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);
}
});
}
});
}
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override public void cancel() {
delegate.cancel();
}
@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();
}
}
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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 的enqueue 的方法,我们都知道这个 call 对象是我们创建的 okhttpcall,那我们继续往下看,看看okhttpcall 做了什么 :
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
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) { //如果call 为null 去创建
try {
call = rawCall = createRawCall(); //注解①
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(new okhttp3.Callback() { //在一系列判断之后,说明请求可以发送,那么调用 okhttp 本身的 call 发送请求
@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();
}
}
});
}
可以看到,最后调用了 callback 的 onResponse 方法,那这个方法其实也就是回调了我们的 ExecutorCallbackCall 中的 Callback ,那我们接下来看一下代码:
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() { //调用了 callbackExector
@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);
}
});
}
});
}