持续创造,加速成长!这是我参加「日新方案 6 月更文应战」的第22天,点击检查活动详情
创立Retrofit实例
Retrofit
选用结构者形式来创立实例。
new Retrofit.Builder()
.client(okhttpClient)
.baseUrl(baseUrl)
.addConverterFactory(converterFactory)
.addCallAdapterFactory(callAdapterFactory)
.build();
Retrofit.Builder
Retrofit.Builder
是Retrofit
的静态类部类,它有以下属性
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
-
platform
platform表明Retrofit当前运转的渠道。它不能经过外部设置,只能由Retrofit主动识别。 -
callFactory
callFactory表明网络恳求器的工厂,首要作用是生成网络的恳求器Call
,一般情况下咱们经过Builder#client()
办法设置为OkHttpClient
,当然,咱们也能够经过Builder#callFactory()
设置自定义工厂。 -
baseUrl
baseUrl是咱们网络恳求中的根底Url,列如域名,一般情况下都是调用Builder#baseUrl(String)
设置一个字符串,Retrofit
会调用Retrofit#baseUrl(HttpUrl)
办法主动转化成HttpUrl
类型。 -
converterFactories
数据转化器列表,将恳求到的数据转化成咱们指定的类型。 -
callAdapterFactories
恳求适配器列表,默许情况下咱们得到的回来成果是Call<R>
类型,经过自定义恳求适配器,咱们能够将成果转化为咱们需求的类型,比如配合RxJava
得到Observable<R>
。 -
callbackExecutor
回调履行器,用于Call#enqueue()
办法中,可完成线程切换,假如不指定,就会获取platform
的defaultCallbackExecutor
。 -
validateEagerly
是否提早对接口中的办法进行验证,假如Service声明的办法非常多,提早会集验证尽管能在早期就发现错误的办法,可是或许形成显着的功能损耗,所以一般在测验阶段设置为true确保即使发现问题,在正式环境中设置为false,这样接口中的办法就会分散验证,确保了功能问题。
创立Retrofit.Builder实例
Builder(Platform platform) {
}
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
}
Retrofit.Builder
供给了三个结构函数,可是暴露给外部调用的就只有无参结构函数,调用的时分会主动获取当前渠道类型,然后调用Builder(Platform platform)
办法进行初始化,同时Retrofit
也供给了快速仿制一个现有的Retrofit.Builder
的办法。
public Builder newBuilder() {
return new Builder(this);
}
经过调用Retrofit#newBuilder()办法,内部就会调用Builder(Retrofit retrofit)结构函数,从而快速创立一个Builder,详细仿制逻辑如下
Builder(Retrofit retrofit) {
//1
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
//2
for (int i = 1,
size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
i < size;
i++) {
converterFactories.add(retrofit.converterFactories.get(i));
}
//3
for (int i = 0,
size =
retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
i < size;
i++) {
callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
}
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
- 能够看到即使是从一个现有的Retrofit快速创立一个Builder,platform属性也是由Retrofit主动识别,然后初始化。
- Retrofit在创立的时分会主动增加platform.defaultConverterFactories和BuiltIntConverters,所以这儿仿制的时分converterFactories就不需求再增加这两个了。
- 关于callAdapterFactories的增加和converterFactories相似。
设置baseUrl
public Builder baseUrl(URL baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(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有3个重载办法,无论调用那个都需求满意下面两点
- baseUrl不能为null。
- baseUrl必须以“/”结束。
生成Retrofit实例
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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory,baseUrl,unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories),callbackExecutor,validateEagerly);
}
build()办法首要履行了以下操作
- 检查baseUrl,假如为null直接抛出异常。
- 检查网络恳求器工厂callFactory,假如没有设置就默许运用OkHttpClient目标。
- 检查回调履行器callbackExecutor,假如没有设置就默许运用当前platform供给的默许履行器,关于Android渠道来说,运用的是MainThreadExecutor
- 增加恳求适配器,包括渠道供给的和用户自定义的。
- 增加数据转化器,包括BuiltInConverters和渠道供给的以及用户自定义的。
- 将converterFactories和callAdapterFactories转化成只读的List,然后创立Retrofit。
创立API接口实例
有了Retrofit实例之后,调用其create()办法获取API接口实例,在此之前,咱们先预备一个GitHubService
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
然后调用create()办法
GitHubService service = retrofit.create(GitHubService.class);
Retrofit.create()
create()办法完成比较简单,首要是运用动态代理生成传进来的API接口的实例。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[]{service},
new InvocationHandler() {
//省掉invoke()完成
});
}
这儿首要做了2件事。
- 验证APIService
- 使用动态代理生成APIService实例。
验证APIService
接口验证
private void validateServiceInterface(Class<?> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque<Class<?>> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class<?> candidate = check.removeFirst();
if (candidate.getTypeParameters().length != 0) {
throw new IllegalArgumentException(//......省掉异常);
}
Collections.addAll(check, candidate.getInterfaces());
}
if (validateEagerly) {
//......省掉办法验证
}
}
validateServiceInterface从以下方面进行检测
- APIService只能是一个接口类型。
- APIService以及其承继的接口不能包括泛型参数。
- 假如设置validateEagerly为true,就会立即对APIService中的办法进行检测,提早检测尽管能及时发现异常办法,可是会形成功能损耗。
办法验证
private void validateServiceInterface(Class<?> service) {
//......省掉接口验证
if (validateEagerly) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
能够看到,提早验证会跳过default办法和static润饰的办法。关于其他办法会调用loadServiceMethod()进行加载。
加载办法
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null)
return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
加载ServiceMethod是一个耗时的进程,所以这儿运用了缓存,关于加载过的办法,会缓存到serviceMethodCache中,serviceMethodCache定义如下:
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
ConcurrentHashMap是线程安全的,假如serviceMethodCache中有当前method则直接取出回来,不然调用ServiceMethod.parseAnnotations()创立一个ServiceMethod,然后放入serviceMethodCache并回来成果。
ServiceMethod的parseAnnotations办法会创立ServiceMethod,这儿只暂时只重视主流程,就不深入检查。
Method.invoke()
public <T> T create(final Class<T> service) {
//......省掉其他代码
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
}
首要,假如当前办法method来源于Object,则正常调用,关于其他办法,假如是default办规律交由渠道platform的invokeDefaultMethod()办法履行,不然将method转化成ServiceMethod然后履行。
履行恳求
经过前面咱们获取到了APIService的实例,然后经过它就能够调用详细办法,然后履行恳求
Call<List<Repo>> repos = service.listRepos("user").execute();
恳求的履行有同步和异步两种,这儿以同步为例
//OkHttpCall.java
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = getRawCall();
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
能够看到Retrofit最后其实是调用来的OkHttp的Call履行了恳求,它首要做了以下操作
- 判别恳求是否履行过,假如履行过了就抛出异常。
- 经过getRawCall()办法将retrofit2.Call转化成okhttp3.Call。
- 经过okhttp3.Call履行恳求。
- 上一步履行恳求回来的成果是okhttp3.Response,经过parseResponse()将okhttp3.Response转化为retrofit2.Response。
到这儿Retrofit运用的主流程剖析完了,关于Call和Response转化等源码将在后边进行剖析。