前文我们分析了Retrofit
中builder内部类的成员变量的作用以及创建的一些方法baseUrl
,addConverterFactory
, addCallAdapterFactory
,详细可以看下上一篇文章
【一起学习Android开源框架】Retrofit源码解析-2(第四部分))
好的,话不多接下来我们继续分析Retrofit
,Let's go
build方法创建流程
我们需要调用build
方法来完成retroifit
对象创建,接下来我们看看这个方法到底做了哪些工作呢? 来看下它的源码
-
首先它会对
baseUrl
进行一个非空的判断,如果是空的时候会抛出异常if (baseUrl == null) { throw new IllegalStateException("Base URL required."); }
-
baseUrl
不为空的时候,首先先进行创建callFactory
网络请求指示器,用于产生网络的call
工厂,也就是实际的http
请求,那么它为空的时候就是默认创建OkhttpClient
,其实就已经表明了Retrotfit
就是默认使用Okhttp
进行网络请求的,这是第一步okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); }
-
第二步,这里主要是初始化回调方法执行器,下面
callbackExecutor
主要用在异步请求,大家知道这个时候肯定会在子线程做耗时操作,但是最后都要回到UI线程进行显示,此时callbackExecutor
就派上了用场;如果它是空的话,会默认提供一个回调执行器,在platform
中的defaultCallbackExecutor
,其实就是主线程的executor
,后面再详细说明Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); }
-
第三步,会创建一个
adapterFactories
的ArrayList
,用于配置网络请求适配器工厂,然后再将平台默认的adapterFactory
添加这个集合当中// Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
-
接着第四步,和上面差不多方式,也是创建一个
ArrayList
,配置数据转换器的工厂,它传入的成员变量就是我们前面配置的convertFactories
// Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // 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()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories());
-
最后会将前面创建好的所有变量会传入到
Retrofit
对象中进行重建return new Retrofit( callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
总结一下build
方法,其实就是通过内部类,将Retrofit
所有成员变量逐个配置,最后将Retrofit
对象重建
上面我们已经了解了整体
Retrofit
构建流程,接下来我们来具体了解网络请求适配器和数据转换工厂的具体原理,首先我们来看当时创建的时候所设置的RxJavaCallAdapterFactory
适配器
RxjavaCallAdapterFacotory
内部构造与工作原理
首先我们来看下RxjavaCallAdapterFacotry
内部的源码,可以看到它是继承Factory
类,可以看到,追本朔源,这个Factory
其实定义在CallAdapter
当中
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static RxJavaCallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJavaCallAdapterFactory(scheduler, false);
.....
}
关于这个CallAdapter
我想我们还是有必要去梳理下它的流程,它是如何在Retrofit
当中工作的?先看下它的源码
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
public abstract @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
其实不难看出,callAdapter
它的作用就是把Call<T>
泛型转换成java
对象;值得注意下,这里的Call
对象和Okhttp
当中其实是不一样的,Retrofit
中的Call
是对Okhttp
的Call
进行了封装,所以说我们通过Retrofit
进行网络请求都是通过Okhttp
来,可以理解为Retorfit
是为Okhttp
封装的一层壳
但是Call<T>
泛型转换成java
对象,不是直接转换的,是有个过程的,可以看下下面的流程图
我们创建好
Retrofit
中的Call
对象,然后发送一个http
请求,拿到服务器返回给我们的数据,这时候就通过converter
数据转换器才转换成java
对象
回到代码,来看下callAdapter具体做了什么
-
先看下
responseType()
这个方法,有一个返回值类型Type
,它的作用就是用于返回http
,返回的是解析后的类型,什么意思呢,简单来说,这里的Type
并不是接口返回的类型,而是它返回类型泛型中的实参 -
接着看
adapt
这个方法,它会传入Call<R>
这个对象,有一个T这个泛型,它是需要我们转换成接口的对象类型;如果对应的是Rxjava
的话,那么这个T泛型就是Rxjava
中的类型,之后会对RxjavaConvertAdapter
进行分析 -
接着看
Factory
这个抽象类,里面有个get
方法,它是根据接口返回的注解类型得到实际需要的callAdapter
; 关于getParameterUpperBound
不用太过关注,它会调用我们的工具类,返回的是我们泛型参数的上限;重要的是getRawType
方法,获取我们的原始类型,这和我们判断选择不同的adapter
有着直接的联系RxjavaCallAdapterFactory实现流程
好了,现在我们来回到RxjavaCallAdapterFactory
源码当中,在此之前,我们先来梳理下它的流程
- 首先实现
CallAdapter
当中的Factory
抽象类,用来提供具体的适配逻辑 - 将我们的
CallAdapter
通过add
方法添加到Retrofit
当中(注册CallAdapter) - 调用
Factory.get
进行获取CallAdapter
- 最后调用
CallAdapter
中的adapt
方法,用它来转换成每个平台所适用的类型
我们来具体看下代码是怎么实现的
继承Factory
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory {
....
}
注册CallAdapter
在我们构建Retrofit
的时候,调用addCallAdapterFactory
就可以注册RxjavaCallAdapterFactory
,这里也可以添加自定义的CallAdapter
不同平台支持的类型
addCallAdapterFactory(RxJavaCallAdapterFactory.create())
调用Factory.get方法获取CallAdapter
我们回到RxjavaCallAdapterFactory
当中,先来看下get
方法,代码如下所示
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
if (isCompletable) {
return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
}
.....
//最终返回一个RxJavaCallAdapter 进行类型转换
return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
false);
}
这里基本上这些逻辑都是判断这个rawType
是否是Rxjava
类型,就不详细赘述了,只要知道最终都会返回RxjavaCallAdapter
具体实现对象,然后就调用adapt
方法进行最终的call
类型转换
adapt请求类型转换
我们先来看下代码,这里是RxjavaCallAdapter
中的调用adapt
方法
@Override public Object adapt(Call<R> call) {
OnSubscribe<Response<R>> callFunc = isAsync
? new CallEnqueueOnSubscribe<>(call)
: new CallExecuteOnSubscribe<>(call);
OnSubscribe<?> func;
if (isResult) {
func = new ResultOnSubscribe<>(callFunc);
} else if (isBody) {
func = new BodyOnSubscribe<>(callFunc);
} else {
func = callFunc;
}
Observable<?> observable = Observable.create(func);
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isSingle) {
return observable.toSingle();
}
if (isCompletable) {
return observable.toCompletable();
}
return observable;
}
很显然,可以看到,这里就用到Rxjava
的知识了,由于方法里涉及到Rxjava
中的几个类以及几个变量(IsFlowable
,isSingle
,isCompletable
,isBody
,isResult
),还是需要了解,不然很有可能看这块代码会一头雾水,可以参考了下面两篇结合官网进行辅助理解
看完之后大概了解了,再回过头来,我们先假设请求的真实类型rawType
用的就是Observable
,那么isFlowable
, isSingle
, isMaybe
都是 false的,回到之前的那个获取泛型参数的类型上限,根据源码提供的注释,我们就可以知道就是获取Observable<T>
中T的类型上限;一般情况下,这个T
类型就是JavaBean
,所以isResult
为false,isBody
为true
知道了这些变量后,然后再看上面的adapt
方法
- 首先看到
isAnsync
这个是由RxjavaCallAdapterFactory
创建的时候就确定是false
了,所以这里会创建一个CallExecuteOnSubscribe
对象 - 接着根据前面的分析结果,
isBody
为true,所以得到的是一个BodyOnSubscribe
对象 - 最后返回这个
observable
,相对于我们调用接口方法返回就是一个BodySubscribe
对象
到目前为止,我们已经了解了,RxjavaCallAdapterFactory
的adapt
方法就是利用Rxjava
中的操作符以及订阅来完成了整个类型适配转换的过程,感兴趣的小伙伴可以继续深入学习这块内容,它具体是如何适配的?由于其中内容过多,就不详细展开了
小结
简单来说,Retrofit
中整个网络适配器CallApdater
流程,大致如下
- 我们获取到一个
Call
对象,拿到这个Call
对象去执行http
请求,而Retrofit
调用这个Call
请求,最终调用的还是okhttp
里面的Call
请求,只不过对其进行了封装,通过这样我们就可以获取到服务器端返回的数据 - 获取到数据之后我们就会调用
converter
数据转换器来把我们需要的对象转换出来 - 具体实现可参考上文
RxjavaCallAdapterFactory
的阐述