在安卓开发中,我们从之前使用安卓6.0的HttpClient,到使用HttpUrlConnection替代HttpClient,再到使用各种第三方网络请求框架实现网络请求。网络请求比较热门的第三方开源框架有HttpUtils、Vollery、OkHttpUtils等。但是目前比较火的还是网络请求的混合三打Rxjava+Okhttp+Retrofit。而且我们用过的都知道这三个框架各有各的职责,相辅相成。
其中Retrofit不是一个网络请求框架,它只是一个网络请求接口的框架封装,通过接口的形式定义接口,然后使用注解配置请求参数,最后生成一个个网络请求的call对象,实际请求还是交给了和它搭配的OkHttp框架。
如果你还是不能理解,那么我建议你直接看Retrofit的官网,看完官网你就更疑惑了!
A type-safe HTTP client for Android and Java
官网介绍了Retrofit的使用,但是根本没有说Okhttp的底层支持,难道之前说的直接使用Retrofit实现网络请求是真的?那么我就建议你查看一下Retrofit的Github。
Github也并没有过多的介绍Retrofit的网络请求实现,所以现在我们只能通过查看Retrofit的源码进行自己追踪了。
我们发现Retrofit源码里面并没有OkHttp的代码实现,也就是说,**单独使用Retrofit是无法实现网络请求的!**但是我们发现,Retrofit源码里面有一个OkhttpCall对象!
其实最主要的还是ServiceMethod类,它的注释如下:
Adapts an invocation of an interface method into an HTTP call.
它就是通过动态代理的方式实现了把一个个的网络接口抽象解析成了一个个的OkHttp的call对象。
那么Retrofit对象是如何和Okhttp进行关联的呢?这里我们就想起来了。
//创建RetroFit对象
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(url)
.build();
client()方法里面除了抛空指针异常外,就定义了一个Retrofit成员变量:
private @Nullable okhttp3.Call.Factory callFactory;
/**
* Specify a custom call factory for creating {@link Call} instances.
* <p>
* Note: Calling {@link #client} automatically sets this value.
*/
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
我们发现我们通过client()方法传入到Retrofit的Okhttp对象被转成了父类,之所以可以这样是因为OkHttp实现了Call接口的内部接口:
// 接口里面定义接口,内部接口返回外部接口,这种方式简化获取外部接口的成本
interface Factory {
Call newCall(Request request);
}
子类转成了父类,那么调用这个被转成父类的子类方法,那么如果父类和子类里面有相同的同名方法,那么最后调用的是谁的方法呢?
public class AParent implements SameMethod{
@Override
public void fly() {
KLog.e(">>>>>>>>>>>>>>", "父类开始飞...");
}
}
public class BSon extends AParent implements SameMethod{
@Override
public void fly() {
KLog.e(">>>>>>>>>>>>>>", "子类开始飞...");
}
}
BSon bSon = new BSon();
bSon.fly();
AParent aParent = new AParent();
aParent.fly();
//子类转成父类之后,开辟内存空间的是子类对象,所以内存方法还是子类的
AParent parent = new BSon();
parent.fly();
这里其实考察的是我们对Java的三大特性封装、继承、多态的一个理解,子类继承父类,就会有父类的方法,但是子类复写了父类的方法,而且new对象开辟的是子类对象,所以就算是子类被转成了父类,调用同名方法(子类和父类有一个同名方法,不是复写也是一样的效果)之后,还是子类的方法。
2019-12-20 15:35:21.549 19093-19093/? E/>>>>>>>>>>>>>>: [ (BSon.java:8)#Fly ] 子类开始飞...
2019-12-20 15:35:21.550 19093-19093/? E/>>>>>>>>>>>>>>: [ (AParent.java:9)#Fly ] 父类开始飞...
2019-12-20 15:35:21.550 19093-19093/? E/>>>>>>>>>>>>>>: [ (BSon.java:8)#Fly ] 子类开始飞...
所以,我们知道了Retrofit通过让OkhttpClient对象实现一个Call接口的内部接口来获取Call对象,并且在内部把OkhttpClient转成了Call接口的内部接口实现了代码之间的解耦,真是很妙!
private @Nullable okhttp3.Call.Factory callFactory;
但是这个callFactory其实又是实际的OkHttpClientr对象具体实现,参数配置已经完成
然后我们使用Retrofit需要注意的就是三个框架是否是相同的版本,如果不是相同的版本就可能会导致兼容问题:
//network
"okhttp" : "com.squareup.okhttp3:okhttp:3.10.0",
"retrofit" : "com.squareup.retrofit2:retrofit:2.4.0",
"converter-gson" : "com.squareup.retrofit2:converter-gson:2.4.0",
"adapter-rxjava" : "com.squareup.retrofit2:adapter-rxjava2:2.4.0",
比较难理解的还是RxJava框架,因为Okhttp其实就是底层通过HttpUrlConnection来实现网络请求的框架,但是RxJava确实分为Retrofit内置的默认线程调度器和完整的Rxjava源码。
我们首先通过查看RxJava的Github源码,比较好的解释博客。
但是我们却搜不到RxJava的官网?RxAndroid是RxJava的扩展版本,主要是为了更好的适配安卓系统环境。在网络请求中的使用就是把网络请求数据返回切换到主线程进行处理:
/**
* 线程调度器
*/
public static ObservableTransformer schedulersTransformer() {
return new ObservableTransformer() {
@Override
public ObservableSource apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());//这里把线程观察者切换到主线程
}
};
}
RxAndroid整个框架只有4个类,主要的作用就是让Rxjava更适配安卓系统,把网络请求数据返回到主线程进行处理。
所以网络请求框架核心功能代码还是Okttp,但是Rxjava作为一个响应式编程的框架,后期还是需要好好研究一下,待更新!