前文我们分析了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的阐述