volley学习笔记四

经过前三篇的学习,想必对volley的使用以及自定义有了一定的了解。接下来这篇文章是郭神volley系列的最后一篇文章,将带领我们从源码角度来学习volley框架。加把劲儿,我们离掌握volley已经不远了。

由于本篇幅是学习笔记,所以只是记录一下博主自己在学习时所见及所想。很多可能看起来觉得莫名其妙的话可能是因为缺少了原文中的代码以及图示造成的。这里不得不佩服一下郭霖大神,写博文真的很用心。如果看不懂的话,还是推荐去读原文 Android Volley完全解析(四),带你从源码的角度理解Volley接下来,开始今天的主题。

关于volley,在官方文档中已经给出了一张volley工作流程图。这张图大家刚开始看会看的一头雾水,但是分析过源码之后,就能够理解了。

那么就从源码分析开始吧。源码那么多,要从哪里开始看起呢,还记不记得RequestQueue对象,这个是调用Volley.newRequestQueue方法来获取的。这个方法只是调用了newRequestQueue的方法重载,并给第二个参数赋值为null,调用了2个参数的newRequestQueue。

在2参数newRequestQueue方法中,stack等于null时,则会去创建一个HttpStack对象。如果手机系统版本号大于9,则创建一个HurlStack实例。否则创建一个HttpClientStack实例。HurlStack内部使用HttpURLConnection进行网络通讯。而HttpClientStack内部使用HttpClient进行网络通讯。具体为何这样选择,还要再看Android访问网络,使用HttpURLConnection还是HttpClient。

创建好stack对象后,又创建一个Network对象。创建时以stack对象为入参,之后又创建一个RequestQueue对象。创建需要两个参数,一个是DiskBasedCache(缓存对象),一个是network对象。创建好队列对象之后,启动queue的start方法,之后return queue对象。这样newRequestQueue方法就执行完了。

接着,让我们看一下RequestQueue中的start方法里都有什么。start方法中代码并不多。进入后先调用stop方法。注解看到是确保所有当前运行的dispatchers都让他们停止。之后创建一个CacheDispatcher实例,然后调用dispatcher的start方法。接着在一个for循环里去创建NetworkDispatcher实例,并分别调用它们的start方法。这里CacheDispatcher和NetworkDispatcher都继承自Thread,而默认情况下for循环会执行四次,也就是说当调用了volley.newRequestQueue方法之后,后台会有五个线程运行。不断等待网络请求的到来。其中cacheDispatcher是缓存线程,networkDispatcher是网络请求线程。

得到了RequestQueue之后,我们需要构建相应的Request,然后调用RequestQueue的add方法将Request传入就可以完成网络请求操作了。add方法一定拥有非常复杂的逻辑。

在add方法中,可以看到,在第11行时候会判断是否可以缓存,如果不能缓存,在第12行就会将请求加入网络请求队列。如果可以缓存,就在第33行将请求加入缓存队列。默认状态下每条请求都是可以缓存的,也可以通过setShouldCache(false)方法改变这一属性。

加入缓存队列中,在后台等待的缓存线程就要运行了,让我们看一下CacheDispatcher中的run方法。

CacheDispatcher继承自Thread。重写了run方法。在代码11行出,有一个while(true)循环,说明缓存线程始终是在运行的。接着在第23行尝试从缓存当中取出响应结果。如果为空的话,把这条请求加入网络请求队列中,如果不为空再判断该缓存是否已过期。如果过期,同样把请求加入网络请求队列。否则就认为不需要发送网络请求,直接取缓存中的内容。之后会在第39行调用Request的parseNetworkResponse方法来对数据进行解析,再往后就是将解析出来的数据进行回调了。这部分代码先跳过,因为它的逻辑和NetworkDispatcher后半部分的逻辑基本相同,等下合并起来一起看就好。先来看一下NetworkDispatcher中是怎么处理网络请求队列的。

NetworkDispatcher同样继承自Thread,重写run方法。与CacheDisparcher类似,也是有一个while(true)循环,保证线程一直运行。在第28行的时候会调用Network的performRequest方法来发送网络请求。而Nerwork是一个接口,具体实现的是BasicNetwork,让我们来看一下performRequest方法。

BasicNetwork继承自Network。这里面大多数代码不需要我们了解,需要注意的是这里面调用了HttpStack的performRequest方法。这个httpStack就是一开始调用newRequestQueue方法时创建的实例。默认情况下,根据版本号是否大于9创建HurlStack对象或HttpClientStack对象。这两个对象分别使用HttpURLConnection和HttpClient来发送网络请求。之后将服务器返回的数据组装成一个NetworkResponse对象进行返回。

在NetworkDispatcher中收到NetworkResponse这个返回值,又会调用Reqeust的parseNetworkResponse方法来解析NetworkResponse中的数据。以及将数据写入到缓存。这个方法的实现是交给Request的子类来完成。在解析完NetworkResponse中的数据之后,又会调用ExecutorDelivery的postResponse方法来回调解析出的数据。其中,在mResponsePoster的execute方法中传入了一个ResponseDeliveryRunnable对象,就可以保证该对象中的run方法就是在主线程当中运行的了。

ResponseDeliveryRunnable实现了Runnable接口。其中的deliverResponse方法就是我们自定义Request时需要重写的另外一个方法。每一条网络请求的响应都是回调到这个方法中。最后我们在这个方法中将响应的数据回调到Response.Listener的onResponse方法中就可以了。


好了,到这里我们就把volley的完整执行流程全部梳理了一遍,再来回顾一下一开始看到的官方提供的那张图吧。

蓝色部分代表主线程,绿色部分代表缓存线程,橙色部分代表网络线程。我们在主线程中调用RequestQueue的add方法来添加一条网络请求,这条请求会先被加入到缓存队列当中。如果发现可以找到相应的缓存结果,就直接读取缓存并解析。然后回调给主线程。如果缓存中没有找到结果,则将这条请求加入到网络请求队列中,然后处理发送的HTTP请求,解析响应结果,写入缓存,并回调主线程。


至此,郭神的volley源码解析一章的学习就告一段落了。稍作休息,让我们用自己的话总结一下。

volley的学习正是由博主的一次面试被问住所引起的。那么让我们回到面试时的那个问题。volley框架的网络请求,是如何是实现的?

这个就要从创建一个RequestQueue对象说起。在Volley.newRequestQueue(context)方法中,调用了两个参数的newRequestQueue方法。第二个参数是httpStack对象,这里传空。之后在2个参数的方法中,对httpStack对象进行了初始化,若版本大于9,则创建HurlStack,否则创建HttpClientStack。之后还要创建网络请求Network。这里new的对象是BasicNetwork,因为Network是一个接口,具体实现是BasicNetwork。

BasicNetwork的构造方法参数是前面创建的stack对象。之后调用RequestQueue的构造方法,注意之前的是newRequestQueue。RequestQueue的构造方法参数是刚刚创建的network对象。创建完RequestQueue之后,调用它的start方法。之后返回queue。newRequestQueue方法结束。

start方法内部进行了什么操作呢。这里先创建了一个CacheDispatcher实例,之后调用它的start方法。接着在一个for循环里创建NetworkDispatcher实例,并调用它的start方法。这里CacheDispatcher和NetworkDispatcher都是继承自Thread,并重写了run方法。从名字中可以看出一个是缓存线程,一个是网络请求线程。

在得到了请求队列RequestQueue后,在构建出相应的Request,之后调用mQueue的add方法就可以完成网络请求。add方法里究竟完成了哪些操作。在add方法中先判断是否可以缓存,如果不可以,则直接加入网络请求中。如果可以,则加入缓存请求队列中。加入缓存请求队列中之后,一直在后台等待的缓存线程CacheDispatcher就要运行起来了。看看CacheDispatcher重写的run方法。

在CacheDispatcher中,一直有一个while循环在保持着,首先尝试从缓存当中取出响应结果,如果为空则加入网络请求队列。如果不为空,判断缓存是否已过期,过期仍然加入请求队列。如果没过期,则直接用缓存中的数据。调用Request中的parseNetworkResponse方法来解析数据。之后将解析出来的数据进行回调。

NetworkDispatcher同样继承自Thread,重写run方法。其中也有一个while循环一直保持着。这里调用了Network中的performRequest方法来发送网络请求。BasicNetwork是Network的具体实现,里面调用了httpStack的performRequest方法。在NetworkDistpatcher中抽到了NetworkResponse返回值后,调用Request的parseNetworkResponse方法来解析NetworkResponse中的数据。之后在主线程中回调。


概括起来就是有两种Dispatcher,一种是缓存请求,一种是网络请求。在请求队列的start方法中会创建这两种Dispatcher,并调用start方法。

得到队列后,创建request,使用add方法加入队列。add方法里判断是否支持缓存,支持就加入缓存队列,不支持就加入网络请求队列。缓存队列里判断是否有缓存,没有则加入网络请求,若有但过期了仍然加入网络请求。有,并且没有过期则直接取缓存中的数据。解析并返回,回调主线程。网络请求中调用network中的performRequest发送网络请求。而Network的具体实现BasicNetwork中调用了httpStack的performRequest来发送网络请求。之后NetworkDispatcher中收到了NetworkResponse的返回值,在调用Request中的response解析数据,并写入缓存,之后调主线程回调。


好了,重复写的话有点多,但是多写一遍就加深一遍印象。希望没有理解volley网络框架原理的读者,也试着能用自己的话表述出来大概流程就可以了。其实在学习过程中,还遇到了一些不理解的概念,比如HttpStack,在判断版本号的时候会创建两种不同的Stack,这两种不同的Stack中又由两种不同的HttpClient实现。一个是HttpURLConnection一个是HttpClient。这些概念在后续的学习中要弄清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值