标签(空格分隔): Android
源码分析篇#
官方整个请求流程
这个图的原理在郭霖对volley的分析的最后有讲
工作流程原理:
1.使用Volley的第一步,首先要调用Volley.newRequestQueue(context)方法来获取一个RequestQueue对象,在这期间去创建一个HttpStack对象,这里会判断如果手机系统版本号是大于9的,则创建一个HurlStack的实例,否则就创建一个HttpClientStack的实例。实际上HurlStack的内部就是使用HttpURLConnection进行网络通讯的,而HttpClientStack的内部则是使用HttpClient进行网络通讯的;然后用Network对象去封装HttpStack对象;然后调用RequestQueue的start()方法
2.在start()方法里面默认创建了一个CacheDispatcher缓存线程的实例,默认创建四个NetworkDispatcher网络请求线程的实例;并且都调用这五个线程的start()方法,让这五个线程在后台一直跑起来,一直监听是否有新的request加入,一旦发现就执行相应的操作。
【这里的只有五个线程,不是一个线程池,所以volley可能会出现当一个线程异常退出之后,没有线程补充的情况】
3.经过上面的第一点与第二点之后,RequestQueue的实力应已经创建好了
4.在我们自己创建好相应的Request网络请求之后,调用RequestQueue的add()方法将Request传入就可以完成网络请求操作,add()方法请见下面的流程图
问题:下面的等待队列有啥用?准确来说只是一个集合
private final Map<String, Queue<Request<?>>> mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
维护了一个等待请求的集合,如果一个请求正在被处理并且可以被缓存,后续的相同 url 的请求,将进入此等待队列。
所有等待Request,这是Volley做的一点优化,想象一下,我们同时发出了三个一模一样的Request,此时底层其实不必真正走三个网络请求,而只需要走一个请求即可。所以Request1被add之后会被调度执行,而Request2 和Request3被加进来时,如果Request1还未执行完毕,那么Request2和 Request3只需要等着Request1的结果即可。即等Request1的请求成功返回后,这时会自动添加到缓存中,然后再将等待队列(等待集合的Request2和Request3添加到缓存队列中,让缓存请求处理线程CacheDispatcher自动处理,从缓存中直接取到数据)
请求队列: RequestQueue
缓存队列:其中的Request需要执行查找缓存的工作
网络工作队列 :其中的Request需要被执行网络请求的工作
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
这里的是维护了一个正在进行中,尚未完成的请求集合。
值得注意的是:
源码中有这么一个方法
void finish(Request<?> request)
代表Request 请求结束,然后执行下操作:
1). 首先从正在进行中请求集合mCurrentRequests中移除该请求。
(2). 然后查找请求等待集合mWaitingRequests中是否存在等待的请求,如果存在,则将等待队列移除,并将等待队列所有的请求添加到缓存请求队列中,让缓存请求处理线程CacheDispatcher自动处理。
博客整理的流程图
这图可以结合郭霖的文章一起看郭霖对Volley的分析还有codeKK对Volley的源码分析,如果对Volley已经上手了,需要的是看看volley的内部实现的话,强烈推荐直接看codeKK对Volley的源码分析]
另外:
实现了Comparable接口,因为在Volley中是可以指定请求的优先级的,实现Comparable是为了在Request任务队列中进行排序,优先级高的Request会被优先调度执行,只是优先发送请求给服务端但不一定优先返回。
RequestQueue 中维护了两个基于优先级的 Request 队列,缓存请求队列和网络请求队列。
放在缓存请求队列中的Request,将通过缓存获取数据,那这个缓存是自动实现的吗?还是要像加载图片一样,要自己手动写缓存?
答案是Volley 默认使用的是基于 sdcard 的DiskBasedCache,Volley内部有 Cache.java,缓存接口,代表了一个可以获取请求结果,存储请求结果的缓存。还有代表缓存实体的内部类 Entry,这一切都是自动完成的
但是Volley官方文档上明确说明,只适用于轻量级请求,而不适用数据量较大的请求,比如下载一个50M的文件,原因是Volley默认在请求回来之后,就把数据从IO流里面搞到内存里面了,50M。。。(另外)如果是请求图片的话,一般是自己写Lrucache缓存,虽然Volley默认的是用DiskLruCache作缓存机制,但是毕竟图片还是要加载到内存里面去的,所以如果是大量的图片加载到内存里面去的话,还是会引发OOM,因此还是需要自己手动写缓存,毕竟那个Volley的DiskLruCache只是为了减少去网络请求而已,不是解决加载大量数据到内存的OOM
使用指南篇#
郭霖对于Volley的使用与原理分析文章
初识Volley的基本用法
使用Volley加载网络图片
定制自己的Request
使用HttpURLConnection还是HttpClient