先来梳理一下Retrofit网络通信的过程,这里总结了一下:
网络通信过程:
1.创建Retrofit实例
2.定义一个网络请求接口并为接口中的方法添加注解
3.通过动态代理生成网络请求对象(也就是解析网络请求接口中的注解,解析完成后来配置网络请求参数)
4.通过网络请求适配器将网络请求对象进行平台适配
5.通过网络请求执行器(call Retrofit中的call和Okhttp中的call是一样的)发送网络请求
6.通过数据转换器解析数据
7.通过回调执行器切换线程
8.用户在主线程处理返回结果
从源码详细看看:
创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
先看一下内部类Builder:
/**
* 内部类 Builder
*/
public static final class Builder {
private final Platform platform; // 平台 android java8,默认用的都是android平台
private @Nullable
okhttp3.Call.Factory callFactory; // 请求网络的工厂,默认是okHttp的
private HttpUrl baseUrl; // 网络请求的基地址,传进来的是String,这里要把String转换成HttpUrl
private final List<Converter.Factory> converterFactories = new ArrayList<>(); // 数据转换器工厂
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); // 网络请求适配器工厂
private @Nullable
Executor callbackExecutor; // 执行异步回调
private boolean validateEagerly; // 标志,是否立即解析接口中的方法,动态代理解析接口中的方法的时候用到的
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get()); // 默认安卓平台,里面有默认网络请求适配器call方法
}
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
converterFactories.addAll(retrofit.converterFactories); // 添加设置的数据转换器
// Remove the default BuiltInConverters instance added by build().
converterFactories.remove(0); // 移除默认的数据转换器
callAdapterFactories.addAll(retrofit.callAdapterFactories); // 添加适配器工厂
// Remove the default, platform-aware call adapter added by build().
callAdapterFactories.remove(callAdapterFactories.size() - 1); // 移除默认的适配器
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
/**
* 定制客户端的请求,可定制OkHttpClient 比如添加相应的拦截器等
*/
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
/**
* 自定义网络请求执行工厂,默认的是 okHttp
*/
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
/**
* 设置http的主机名(域名) + 端口号 *以/结尾
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null"); // 先判断 baseUrl是否为空
HttpUrl httpUrl = HttpUrl.parse(baseUrl); // 把baseUrl转换成HttpUrl
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
/**
* 承接上面的方法,解析处理 baseUrl
*/
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); // baseUrl必须用“/”结尾
}
this.baseUrl = baseUrl; // 赋值给内部类的成员变量
return this;
}
/**
* 为对象的序列化和反序列化添加数据转换器工厂.
*/
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* 添加调用适配器工厂 RxJava 的观察者 observe 默认是okHttp的call
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* 执行异步回调
*/
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
/**
* 返回可修改的调用适配器工厂列表.
*/
public List<CallAdapter.Factory> callAdapterFactories() {
return this.callAdapterFactories;
}
/**
* 返回可修改的(数据)转换器工厂列表.
*/
public List<Converter.Factory> converterFactories() {
return this.converterFactories;
}
/**
* 设置标志,是否立即解析接口中的方法,动态代理解析接口中的方法的时候用到的
*/
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
/**
* 根据上面所配置的值创建实例,如果没有自定义配置网络请求,默认创建并使用okHttp请求
*/
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) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 创建并复制网络请求适配器工厂,并添加默认的网络请求适配器
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 创建并复制数据解析器工厂
List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size());
// 首先添加内置转换器工厂。这可以防止覆盖它,确保在使用时是正确的
converterFactories.add(new BuiltInConverters()); // 添加默认的数据转换器工厂
converterFactories.addAll(this.converterFactories); // 添加用户自定义设置进来的数据转换工厂
// https://blog.csdn.net/cilen/article/details/7744969 题外说一下unmodifiableList用法
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
内部类中包含了七个成员变量和三个构造函数:
- 七个成员变量:
private final Platform platform; // 平台 android java8,默认用的都是android平台
private okhttp3.Call.Factory callFactory; // 请求网络的工厂,默认是okHttp的
private HttpUrl baseUrl; // 网络请求的基地址,传进来的是String,这里要把String转换成HttpUrl
private final List<Converter.Factory> converterFactories = new ArrayList<>(); // 数据转换器工厂
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); // 网络请求适配器工厂
private Executor callbackExecutor; // 执行异步回调
private boolean validateEagerly; // 标志,是否立即解析接口中的方法,动态代理解析接口中的方法的时候用到的
- 三个构造函数:
一个是直接传入Retrofit,其他两个是传入平台和空构造函数,不传默认是Android平台。
- 在这个内部类中可以看到很灵活的提供了很多方法:
包括自定义OkHttpClient、网络请求执行工厂(默认是okhttp3)、设置设置http的主机名(域名) + 端口号 *以/结尾、添加数据解析的工厂(例:我们经常使用的GsonConverterFactory.create())、调用工厂的适配器(例:RxJavaCallAdapterFactory.create())...等等。
- 这里需要注意一下:
/**
* 设置http的主机名(域名) + 端口号 *以/结尾
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null"); // 先判断 baseUrl是否为空
HttpUrl httpUrl = HttpUrl.parse(baseUrl); // 把baseUrl转换成HttpUrl
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
/**
* 承接上面的方法,解析处理 baseUrl
*/
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); // baseUrl必须用“/”结尾
}
this.baseUrl = baseUrl; // 赋值给内部类的成员变量
return this;
}
传入的baseUrl必须用“/”结尾,否则会抛出异常。
- 这里涉及到一个类Platform:
class Platform {
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(); // Java8平台
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
@Nullable Executor defaultCallbackExecutor() {
return null;
}
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor); // 创建默认的CallAdapterFactory ---> ExecutorCallAdapterFactory
}
return DefaultCallAdapterFactory.INSTANCE;
}
boolean isDefaultMethod(Method method) {
return false;
}
@Nullable Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, @Nullable Object... args) throws Throwable {
throw new UnsupportedOperationException();
}
/**
* Java 8 平台
*/
@IgnoreJRERequirement // Only classloaded and used on Java 8.
static class Java8 extends Platform {
@Override boolean isDefaultMethod(Method method) {
return method.isDefault();
}
@Override Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
@Nullable Object... args) throws Throwable {
// Because the service interface might not be public, we need to use a MethodHandle lookup
// that ignores the visibility of the declaringClass.
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
return constructor.newInstance(declaringClass, -1 /* trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(object)
.invokeWithArguments(args);
}
}
/**
* Android 平台
*/
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
// 持有有个主线程的Handler,发送响应是事件到主线程
return new MainThreadExecutor(); // 构建一个用来将响应事件发送到Main线程
}
@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()); // 创建主线程的handler
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
可以看到选择Android平台(默认),会默认创造一个MainThreadExecutor主线程执行者,意味着Retrofit的网络请求最终回调到主线程中。
下面接着看看Retrofit中的成员变量:
/**
* Method是http的请求方法,ServiceMethod 代表网络请求接口中,对方法注解后,我们要通过解析,解析
* 之后的对象就是这里的ServiceMethod,和注解中的请求方法成对出现的,一一对应的
* serviceMethodCache用于缓存,请求方法、配置、转换器、适配器等等
*/
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory; // 请求网络okhttp的工厂
final HttpUrl baseUrl; // 网络请求url的基地址
final List<Converter.Factory> converterFactories; // 数据转换器工厂集合,就是把服务端返回的json转换成我们对应的JavaBean,这是个放置数据转换器的工厂
final List<CallAdapter.Factory> callAdapterFactories; // 网络请求适配器工厂集合 ,就是把call对象转换成其他类型,比如转换成RxJava的被观擦者
final @Nullable Executor callbackExecutor; // 用于执行回调的
final boolean validateEagerly; // 表示标志位的,表示我们是否立即解析接口中的方法,动态代理解析接口中的方法的时候用到的
这里重点说一下serviceMethodCache这个Map集合,它是一个ConcurrentHashMap说明是线程安全的。它的key是Method,即网络请求接口定义的带注解的方法(非默认),Value是一个ServiceMethod,ServiceMethod其实就是把网络请求接口中带注解的方法解析之后的对象。
它们是一一对应的,网络请求接口一个带注解的方法(非默认),对应一个ServiceMethod。
最后就是Retrofit的重要内容是怎么把网络接口的注解翻译成一个个http请求:
ServiceApi service = retrofit.create(ServiceApi.class);
Call<String> call = service.tag("android");
- create方法的源码:
/**
* @param service 构建API的生产接口
* @return 返回 构建API的生产接口
*/
@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); // 立即(验证))解析接口中的方法
}
// 通过动态代理将构建API的生产接口的注解翻译成一个个http请求,再由线程池来执行这一个个的网络请求
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)) { //如果该方法是声明为default,则正常调用该方法
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 从缓存ServiceMethod的方法的集合中根据Method获取该ServiceMethod实例对象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); // 创建一个请求执行对象,就是okHttp中的Call
return serviceMethod.adapt(okHttpCall); // 网络请求适配器的使用以及异步执行器的回调
}
});
}
/**
* 会在Retrofit第一次cretae的时候调用
*
* 立即(验证))解析接口中的方法
* @param service 构建API的生产接口
*/
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) { // 利用反射获取生产接口中的所有方法(私有,默认、公有))
if (!platform.isDefaultMethod(method)) { //判断是不是default方法,jdk7以后接口中可以编写方法的实现,但是必须在方法前面设置一个关键字default
loadServiceMethod(method);
}
}
}
/**
* 加载接口中的非default方法,构建一个ServiceMethod对象,以Method为Key,该对象作为value添加到serviceMethodCache集合缓存起来
*/
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;
}
核心就是通过动态代理和反射实现的,上面代码中注释很详尽,这里就不展开细说了。
动态代理的讲解:https://www.jianshu.com/p/2c1173635bc2
PS:这里有一个注意点:
- jdk7以后接口中可以编写方法的实现,但是必须在方法前面设置一个关键字`default'
示例如下:
public interface Test {
// TODO jdk7以后接口中可以编写方法的实现,但是必须在方法前面设置一个关键字`default'
default String setName() {
return "测试";
}
}
接下来就是发起具体的网络请求了,其实就是操作的OkHttp3:
//发送网络请求(异步)
call.enqueue(new Callback<String>() {
//请求成功时回调
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
//请求处理,输出结果
assert response.body() != null;
response.body().toString();
System.out.println("*******" + Thread.currentThread().getName() + "&&&&&&&&");
}
//请求失败时候的回调
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable throwable) {
System.out.println("连接失败");
System.out.println("*******" + Thread.currentThread().getName() + "&&&&&&&&");
}
});
这里用到了网络请求的适配器,在上面我们将默认平台Android的时候。。系统会默认创建一个网络请求适配器ExecutorCallAdapterFactory:
- 我们来看看源码
package retrofit2;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.concurrent.Executor;
import okhttp3.Request;
import static retrofit2.Utils.checkNotNull;
/**
* 默认创建的 CallAdapterFactory,当然也可以自定义RxJava的Observer<Object>,这里只说默认的
*/
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
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);
}
};
}
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor; // 回调的Executor (其实就是Android那个Platform中的MainThreadExecutor)
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池中移除
@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();
}
}
}
打断点,最终走的还是OkHttp的方法:
OkHttpCall
Retrofit的使用:https://www.jianshu.com/p/dac9a1c02525
网友评论