1. 创建ApiService,声明接口相关信息
这里采用的是外观模式,
interface ApiService {
@GET("/users/{user}/repos")
fun listRepos(@Path("user") user: String?): Call<List<String?>?>?
}
2. 创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("")
.addConverterFactory(GsonConverterFactory.create())
.client()
.build()
Retrofit中维护了网络请求所需要的一些信息
public final class Retrofit {
//Mehhod就是ApiService中定义的listRepos,ServiceMethod就是对这个Method的解析和封装
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
//表示一个准备好,可以随时使用的http请求
final okhttp3.Call.Factory callFactory;
//请求通用域名
final HttpUrl baseUrl;
//用于将服务器响应转换为特定的格式
final List<Converter.Factory> converterFactories;
//Call的适配器,根据Retrofit运行的平台不同而不同
final List<CallAdapter.Factory> adapterFactories;
//回调的Executor,用于将回调切换回主线程
final @Nullable Executor callbackExecutor;
//是否提前验证,后面会讲到,默认false
final boolean validateEagerly;
...
}
而Retrofit的创建过程就是通过建造者模式对这些信息进行初始化,.Builder()主要是生成了一个Perform对象,不同平台生成的Perform对象不同,perform对象中保存着一些配置,比如安卓平台下,Builder()生成了一个Android()对象
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
//内部维护了一个主线程的Handler,最终用这个handler实现线程切换,记重点,后面会说
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
.addConverterFactory()就是对converterFactories进行设置,.client()就是对callFactory进行设置,.baseUrl()就是对baseUrl进行设置,这都非常好理解。而在build()中
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//如果没用通过client()方法设置一个callFactory,那么这里就会为你创建一个默认的
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//注意:我们可以通过.callbackExecutor()设置callbackExecutor,如果没有这里会为我们创建一个,也就是上面的Android.MainThreadExecutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 将通过.addCallAdapterFactory()配置的callAdapter.Factory加入list,并将默认的callAdapterFactory放到list的最后一个
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 将通过.addConverterFactory()配置的Converter.Factory加入list
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
//创建Retrofit实例
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
到这里Retrofit就构建完成了,这个时候Retrofit成员变量如下:
- serviceMethodCache:暂时为空
- callFactory:实际上是OkHttpClient对象,可通过.client()配置
- baseUrl:必须要有的,通过.baseUrl()配置
- converterFactories:存放Converter.Factory对象的List,通过.addConverterFactory()配置
- adapterFactories:存放CallAdapter.Factory对象的List,可通过.addCallAdapterFactory()配置,会有一个默认的CallAdapter.Factory对象放在队尾
- callbackExecutor:可通过.callbackExecutor()配置,或者使用默认的MainThreadExecutor
- validateEagerly:默认false
3. 根据ApiService中声明的接口信息创建网络请求
val call = retrofit.create(SampleService::class.java).listRepos("user")
首先我们看create()方法:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
//判断是否需要提前验证
if (validateEagerly) {
//给接口中每个方法的注解进行解析并得到一个ServiceMethod对象,并且以Method为键将该对象存入serviceMethodCache中
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 {
...
//解析method注解进行解析并得到一个ServiceMethod对象,并且以Method为键将该对象存入serviceMethodCache中
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//根据serviceMethod创建OKHttpCall对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//调用OkHttp并返回Call对象
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
所以这一步是一个根据ApiService中声明的接口信息,生成一个Call对象的过程,那么有了OkHttpCall类型的Call对象后,我们就可以开始进行请求了,而OkHttpCall则是OkHttp的包装类:
发送请求
//同步请求
call.execute()
//异步请求
call.equeue()
我们先看execute():
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
//设置同步锁
synchronized (this) {
...
call = rawCall;
if (call == null) {
try {
//创建一个OkHttp的Request对象,并生成一个OkHttp的Call对象
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
//发送同步请求,并用parseResponse承接请求结果,在parseResponse中会调用serviceMethod的toResponse利用配置的Convert将数据解析为Java对象并返回
return parseResponse(call.execute());
}
equeue和execute差不多,也是先调用createRawCall生成一个OkHttp的Call对象,然后调用call.equeue(callback)方法,这里重点看一下传入的callback
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
//这里的callbackExecutor其实就是在Retrofit初始化时,由perform默认生成MainThreadExecutor对象,调用execute会用主线程的handler将这个RunnablePost到主线程中,从而完成线程的切换
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
//同onResponse
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
总结
- Retrofit中根据平台和配置的不同生成并保存了请求中要用到的一些基础配置(利用Perform类)
- SeriviceMethod类则是根据ApiService中的注解信息对请求的一些参数、方式等信息进行一个统一的包装,几乎包括了一个网络请求所需要的所有数据;
发送请求的时候OkHttp需要从ServiceMethod中获取一个Request对象;
解析数据时也需要通过ServiceMethod使用Convert转换为Java对象进行解析;
为了提高效率,Retrofit还会利用serviceMethodCache对解析过的ServiceMethod进行缓存,serviceMethodCache是一个ConcurrentHashMap,这个Map的好处在于线程安全且支持高并发。 - Retrofit进行异步请求后,会在callback中通过handler的方式做一个线程的切换
- 以上所有都是基于简单使用Retrofit的方式,并没有结合Rxjava等其他框架,