前言
Volley是什么鬼?
Volley是谷歌提出的网络通信框架,该框架封装了网络通信和图片加载,使得使用起来更加的简单快捷。
为什么要使用Volley?
- 基本的网络通信框架中,底层实际都封装了两种通信方式:HttpUrlConnectTion和HttpClient。这两种方式实现比较复杂,因此,AsyncHttpClient底层封装了具体的通信方式,而只将接口暴露给用户,用户使用起来十分的方便。
- universal-imageLoader,则将重心放在图片加载,以及图片资源清除等。
这两种框架功能较为细化,因此则显得过于单一。因此google公司发布了Volley这个框架,既满足了网络通信的简单化,又具有了图片加载的功能,同时,增加了自定义的功能,用户可以对该框架进行扩展来满足自己的项目需求。
源代码解析##
请求架构图###
RequestQueue会维护一个缓存调度线程和网络调度线程。当一个请求被加入到队列中后,首先由缓存线程来对该请求进行筛选,如果该请求的内容在缓存中可以找得到话,则缓存线程会来解析缓存内容,并将解析的内容分发到主线程;如果缓存中没有相关的内容时,则缓存调度线程会将该请求移交给网络调度线程中的通信队列中,该线程依次取出队列中的请求,发起http请求,得到回应后,将返回的数据进行解析,并写入缓存中,同时将该内容分发给主线程。
具体源码流程分析###
Volley.newRequestQueue(context),首先调用该类时,重载了newRequestQueue(context,null)方法,在该方法中初始化相关信息,比如缓存地址,HttpStack。其中HttpStack为网络通信的代理类,里面封装着相应的通信实体(在版本大于9,也就是版本大于2.3时,采用的是httpClientStack,里面封装这httpUrlConnection,小于9时,采用的是httpclient),然后生成请求队列实例,并start;
RequestQueue.start() 在请求队列逻辑处理中,会开启两种线程:缓存调度线程和网络调度线程,其中缓存调度线程有1个,而网络调度线程默认有4个。
-
requestQueue.add() 向请求队列中加入请求后,就可以完成网络通信了。那么add里面的操作是什么呢?
- 首先判断该请求是否需要加入缓存
if (!request.shouldCache())
,如果不需要加入,则直接交给网络请求队列; - 需要加入缓存时,会进行判断,看等待队列中是否含有key,如果含有key,则将其数据加入到队列中,放入到该队列中。
Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
;如果没有相同的key,则在等待队列中加入该key,value为null,并加入缓存线程中。接下来,缓存线程就运行起来了
- 首先判断该请求是否需要加入缓存
-
缓存线程 CacheDispatcher 缓存线程的run方法中,执行逻辑如下:
- 该线程
while(true)
,可以看出该线程一直在后台运行。 - 尝试从缓存中取出缓存内容,如果内容为空,则直接就加入到网络请求队列中。缓存内容过期,同理;
- 通过parseNetWorkResponse来对缓存内容进行解析,并回调。
- 该线程
-
**网络通信线程 NetworkDispatcher ** 执行逻辑如下:
- 该线程,也是一直在后台运行;
- 该通过performRequest()发起网络请求。该performRequest实际上调用了BasicNetWork实现,在其内部,调用了httpStack的performStack,而这个就是之前实例化的httpStack。
- 通过parseNetWorkResponse来解析返回的数据,并写入到缓存中。
- 如何回调到主线程中? 通过
ResponseDeliveryRunnable()
方法,将数据传给response.deliverResponse();在该类中,将数据传给response.listener的onResponse的方法中。
Volley的缓存策略###
只采用了磁盘缓存