Retrofit作为主流的网络请求框架,内部封装OkHttp发起请求,也是声明式Http客户端,使用接口 + 注解的方式在接口中编写请求方法,前文铺垫了这么多,接下来我们就正式进入Retrofit的源码之旅
网络通信流程8步骤&7个关键成员变量
在解析retrofit的源码之前,先回顾下retrofit网络通信的八步骤,有一个宏观的认知
网络通信8步
- 创建retrofit实例
- 定义一个网络请求接口并为接口中的方法添加注解
- 通过动态代理生成网络请求对象,也就是解析网络请求接口中的注解
- 通过网络请求适配器将网络请求对象进行平台适配(包括Android,Java8,IOS等的)
- 通过网络请求执行器发送网络请求
- 通过数据转换器解析数据
- 通过回调执行器切换线程
- 用户在主线程处理返回结果
以上就是Retrofit进行网络通信的步骤,大致代码如下所示,相信之前大家已经耳熟能详了
val retrofit = Retrofit.Builder()
.baseUrl("https://www.baidu.com") //请求url地址
.addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //设置Rxjava
.build()
val myInterface = retrofit.create(MyInterface::class.java)
val call = myInterface.getCall()
call.execute()
call.enqueue(object : Callback<List<MyResponse>>{
override fun onResponse(
call: Call<List<MyResponse>>,
response: Response<List<MyResponse>>
) {
}
override fun onFailure(call: Call<List<MyResponse>>, t: Throwable) {
}
})
7个关键成员变量
接下来我们开始看下Retrofit的源码,首先就可以看到它创建了7个变量,先来搞清楚这些成员变量的作用,对之后理解Retrofit通过动态解析挺有帮助的
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
serviceMethodCache
- 它是一个Map对象,这里是ConcurrentHashMap对象,看下它的key值method,也就是http请求的方法,value值是ServiceMethod,看到这里有点懵,查阅资料后才知道它代表网络请求接口中对方法进行解析,然后解析之后的对象就是ServiceMethod,相当于和注解中的@Get,@Post是成对出现的,一一对应;
- 它的作用主要是用于缓存,比如说存储网络请求的配置,还有网络请求的方法,数据转换器,网络请求适配器等等
callFactory
- 它是请求网络OkHttp的工厂,由于retrofit默认的工厂就是OkhttpClient,这个在之前解析Okhttp的时候已经详细提过了,这里就不赘述了,这个工厂的作用就是用于生成我们的OkhttpClient
baseUrl
- 这个很简单了,就是网络请求基础地址url,有了基地址,那就有相对地址,在接口当中的相对地址拼接起来就是个完整的url地址
List<Converter.Factory>,List<CallAdapter.Factory>
- 这两个都是集合,前者是数据转换器工厂的集合,数 据转换器就是对我们请求之后得到的response进行的转换成能用java对象,总的来说它是用于放置数据转换器的工厂;后者是网络请求适配器工厂的集合,把Call对象转换成其他类型,比如说平台想支持Rxjava的话,就可以转换成Rxjava的Call对象,就是用于生产CallAdapter,这里简单说下,后期需要详细说明
Executor
- 这是用于执行回调的,在Android平台当中,会看到Platform这个变量在Retrofit的Builder内部类中,默认使用MainThreadExecutor主线程池;其实我们只要明白,在Retrofit中的网络请求最终都是通过线程池将handler进行调配的,可以处理主线程与子线程的切换;在处理异步的网络请求时就需要它了
validateEagerly
- Boolean类型,这是个标志位,表示的是是否立即解析接口中的方法
Retrofit的Builder内部类
- Retrofit是通过建造者模式构建出来的,我们首先看它的Builder内部类,是一个静态内部类
public static final class Builder {
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;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
....
- 可以看下几个成员变量,Platform表示Retrofit适配的平台,默认情况都是使用Android平台;callFactory表示的是请求网络Okhttp的工厂,默认情况下就是OkhttpClient; baseUrl表示网络请求url地址,需要注意的是这里是HttpUrl,所以需要把String类型的url转换为HttpUrl类型才能够被Retrofit使用;convertFactories表示数据转换器工厂的集合;adapterFactories表示网络适配工厂的集合;callbackExecutor表示执行异步回调的;validateEagerly表示是否需要立即解析接口中的方法,这个标志位用在动态代理要解析定义的注解和方法中,会进行判断;
- 回顾这些成员变量和前面介绍地7个成员变量大体基本是类似地,除了PlatForm是Retrofit所没有的,所以说我们也能看出构建者模式就是通过Builder这个内部类进行配置,通过这个配置就能把Retrofit当中的成员变量初始化
- 接下来我们查看下Builder类的无参构造方法
public Builder() {
this(Platform.get());
}
传入的是Platform.get(),返回的就是适配平台,我们可以继续看下Platorm内部做了什么
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android()
: new Platform(true);
}
private final boolean hasJava8Types;
private final @Nullable Constructor<Lookup> lookupConstructor;
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
Constructor<Lookup> lookupConstructor = null;
if (hasJava8Types) {
try {
lookupConstructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
lookupConstructor.setAccessible(true);
} catch (NoClassDefFoundError ignored) {
} catch (NoSuchMethodException ignored) {
}
}
this.lookupConstructor = lookupConstructor;
可以看到Platform其实就是个单例,它的get方法最终都是调用findPlatform方法,根据不同的运行平台来提供不同的线程池;我们看下findPlatform方法中做了什么操作,它其实就是返回虚拟器所在的那个平台,默认是在Android平台
我们看下这个Android类的代码
class Android extends Platform {
....
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
//通过handler post到主线程
handler.post(r);
}
}
- 它这里会返回一个默认的回调执行器defaultCallbackExecutor,见名知义,简单来说,这个执行器的作用就是用于切换线程,同时在主线程中执行回调方法
- 它会返回一个MainThreadExecutor(),这个在下面已经初始化好了,内部有个Handler调用的是Looper.getMainLooper()这个静态方法,这个Executor已经和主线程(UI线程)绑定了,为了把返回值的处理切换到UI线程, 所以说这也是它能够在主线程回调方法的原因
- 我们回到Builder内部类当中,接下来我们看下Builder的有参构造方法
Builder(Platform platform) {
this.platform = platform;
}
...
这里很简单,看到就是将平台对象进行赋值给Builder内部类的成员变量platform,对于Builder我们日常使用中通常使用空参这个this(Platform.get())设置retrofit使用平台
以上就是对Builder的简单分析, 总结以下,它主要是做了以下工作
- 配置平台类型的对象Platform,默认使用Android
- 配置了网络适配和数据转换的工厂
- Executor执行异步回调,这里只是默认值的初始化,还没有真正部署到Retrofit的成员变量中
总结
这部分主要介绍了Retrofit的builder构建者模式以及builder内部类的成员变量的作用,接下来会继续学习分析Retrofit的源码
未完待续
网友评论