[置顶] Volley源码阅读(0)
2016-11-20 00:03
381 查看
在RequestQueue类中
1、首先看add方法
if (!request.shouldCache()) { mNetworkQueue.add(request); return request; }
在他的add方法中会判断是否需要缓存.shouldCache(),需要则添加到mNetworkQueue网络处理队列,至此返回
否则进入缓存队列处理
synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); if (mWaitingRequests.containsKey(cacheKey)) { // There is already a request in flight. Queue up. Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey); if (stagedRequests == null) { stagedRequests = new LinkedList<Request<?>>(); } stagedRequests.add(request); mWaitingRequests.put(cacheKey, stagedRequests); if (VolleyLog.DEBUG) { VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); } } else { // Insert 'null' queue for this cacheKey, indicating there is now a request in // flight. mWaitingRequests.put(cacheKey, null); mCacheQueue.add(request); } return request; }
在加入缓存队列前每个请求得到都会判断该请求是否正在执行(flight)判断条件就是请求的cacheKey是否对应 map集合mWaitingRequests
2、再来看finish方法(因为上面的mWaitingRequest在finish方法中被处理了)
``` <T> void finish(Request<T> request) { // Remove from the set of requests currently being processed. synchronized (mCurrentRequests) { mCurrentRequests.remove(request); } synchronized (mFinishedListeners) { for (RequestFinishedListener<T> listener : mFinishedListeners) { listener.onRequestFinished(request); } } if (request.shouldCache()) { synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); Queue<Request<?>> waitingRequests = mWaitingRequests.remove(cacheKey); if (waitingRequests != null) { if (VolleyLog.DEBUG) { VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.", waitingRequests.size(), cacheKey); } // Process all queued up requests. They won't be considered as in flight, but // that's not a problem as the cache has been primed by 'request'. mCacheQueue.addAll(waitingRequests); } } } ```
上面代码中做了这些事:
将请求从mCurrentRequests主队列(存了网络队列和缓存队列)移除了,添加了请求完成监听,如果该请求同时是能被缓存的则把存于mWaitingRequests中的相同请求取出并加入mCacheQueue缓存队列。(个人认为这是为了处理多次相同请求能够依次进行缓存,而HashMap不支持相同键值对存在,所以引入mWaitingRequests)
推测引入mWaitingRequest是为了处理相同请求多次依次处理而作为中间存储空间。
从注释中可以看到
* Called from {@link Request#finish(String)}, indicating that processing of the given request * has finished.
finish是在Request中的finish被调用的
那么Request中怎么有RequestQueue对象呢?因为Request中有setRequestQueue,在RequestQueue中的add方法一开始就调用了
也就是说每一个被添加到RequestQueue中Request都与RequestQueue绑定了。
3、看start方法
``` /** * Starts the dispatchers in this queue. */ public void start() { stop(); // Make sure any currently running dispatchers are stopped. // Create the cache dispatcher and start it. mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start(); // Create network dispatchers (and corresponding threads) up to the pool size. for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } } ```
先调用了stop方法,将当前的正在运行的dispatchers全部停掉
再创建了缓存分发线程和网络分发线程
CacheDispatcher()中的参数:mCacheQueue–>缓存请求队列 |
mNetworkQueue–>网络请求队列 |-都是实现Queue接口的PriorityBlockingQueue对象,指针
mCache–>缓存操作对象,默认传入的是DiskBasedCache对象(这里用于读取缓存)
mDelivery–>监听接口传递,是实现了ResponseDelivery的子类ExecutorDelivery的对象
|-它的方法postResponse可以用于绑定Response响应结果给监听器
NetworkDispatcher()中的参数:mNetworkQueue–>网络请求队列
mNetwork–>网络请求对象,能够执行网络请求
mCache–>缓存操作对象,默认传入的是DiskBasedCache对象(这里用于写入缓存)
mDelivery–>监听接口传递,是实现了ResponseDelivery的子类ExecutorDelivery的对象
|-它的方法postResponse可以用于绑定Response响应结果给监听器
4、看cancelAll()、stop()方法:
/** * Cancels all requests in this queue for which the given filter applies. * @param filter The filtering function to use */ public void cancelAll(RequestFilter filter) { synchronized (mCurrentRequests) { for (Request<?> request : mCurrentRequests) { if (filter.apply(request)) { request.cancel(); } } } }
cancelAll()方法用于将当前的mCurrentRequests集合中全部进行标记取消,理论上只能在线程没开启的时候取消
/** * Stops the cache and network dispatchers. */ public void stop() { if (mCacheDispatcher != null) { mCacheDispatcher.quit(); } for (int i = 0; i < mDispatchers.length; i++) { if (mDispatchers[i] != null) { mDispatchers[i].quit(); } } }
stop()方法则是调用线程执行quit()方法,理论上可以停止正在执行缓存和网络任务的线程
@see quit()
public void quit() { mQuit = true; interrupt(); }
quit()方法标记为true,使线程的while循环退出并调用Thread中的interrupt()方法中断线程。
5、看RequestQueue的构造
``` RequestQueue的核心构造器: public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) { mCache = cache; mNetwork = network; mDispatchers = new NetworkDispatcher[threadPoolSize]; mDelivery = delivery; } ```
传入缓存执行对象,Volley中的newRequestQueue(),
网络请求mNetworkQueue和缓存队列mCacheQueue都是 PriorityBlockingQueue对象 RequestQueue存储请求用的是set集合(HashSet)
其他备注
1、 LinkedList类实现了Queue接口2、 锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁,代码块中对该对象有一些处理操作。
3、
//得到Android系统的版本 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
4、TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
5、Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
6、Request中有个isCancel()方法。取消请求,如果请求已经在进行了则不起作用。这个方法是请求还没执行时有作用。也就是说在线程已经开始run了。
7、Request基类中定义了错误监听,因为子类的错误监听都相同,成功的监听都不同,成功的监听结果有String,Json,Image等。
8、Request中有返回监听,有错误返回监听,成功监听有子类设置,有个接口为ResponseDelivery,用于传递监听的,其子类ExecutorDelivery用于绑定Request及其子类的监听与Response的。
9、
BlockingQueue<String> queue = new PriorityBlockingQueue();
这个队列对象相当于指针,对象作为参数传入方法后,改变值会同时在外面被改变;在RequestQueue类中的mNetWorkQueue和mCacheQueue都是这个类型的对象。
//TODO 还有其他的一些关键类再去了解
相关文章推荐
- [置顶] Volley源码看这一篇就够了
- [置顶] 【源码分析】Volley用法及源码分析
- [置顶] Redis客户端Jedis源码阅读及连接池分析
- [置顶] Android网络通信Volley框架源码浅析(一)
- [置顶] nginx源码阅读(二).初始化:main函数及ngx_init_cycle函数
- [置顶] nginx源码阅读(九).事件及连接的定义、连接池
- [置顶] 【经验】轻量化阅读源码初体验sublime+gradlew命令
- Volley源码阅读之网络分发器(NetworkDispatcher)的工作原理
- [置顶] 源码阅读--进程管理
- [置顶] Android网络通信Volley框架源码浅析(二)
- [置顶] android源码阅读--线程间通信Handler消息机制
- [置顶] nginx源码阅读(六).内存池
- [置顶] Elastic-Job-Lite 源码阅读 ---- 作业执行
- 阅读volley的源码HttpStack
- [置顶] JAVA源码阅读——–Integer类
- [置顶] Android网络通信Volley框架源码浅析(三)
- [置顶] nginx源码阅读(八).ngx_events_module模块
- [置顶] 源码阅读---Activity启动中应用进程的创建
- [置顶] Android框架源码阅读指南(博客专栏)
- Volley源码阅读详解(一)---网络任务分发,处理和交付的核心流程