Android网络框架volley学习(六)调度器CacheDispatcher简析
2018-01-25 18:00
471 查看
在前面的分析文章中,我们了解到,当发起一个请求时,首先加入到请求队列中,请求队列中是如何工作的呢?它会首先去缓存队列中取,如果不符合的话另开网络线程去执行这个请求操作。
源码路径RequestQueue#start
本篇文章我们就来详细了解一下两个线程调度器NetworkDispatcher和CacheDispatcher是如何工作的。
接着进行初始化操作。
既然CacheDispatcher是一个线程,那么接着我们就来看下它的run方法。
这里面没有什么大动作,我们来看下里面的processRequest方法是干嘛的。由于这个方法太长,我们一步一步分析。
首先从缓存队列中取出请求,判断是否已经取消了。
接着从缓存中取出这个请求结果。如果不存在在这个请求结果的话,则加入到网络调度线程队列中去。
如果存在这条缓存结果时,继续往下走,然后判断是否过期了。如果过期了则同样加入到网络线程队列中去。
接下来讲缓存的结果解析成response,
接着判断是否需要刷新,不需要的话则直接返回缓存结果,否则加入到网络缓存队列中去。
这里面有个静态内部类WaitingRequestManager,我们来看下表示什么内容。
接着我们看上面用的方法maybeAddToWaitingRequests,字面意思就是可能需要保存到等待请求队列中去。
首先判断这个集合中是否存在当前请求,如果存在的话则表示重复请求,则需要排队等待。
以上便是整个缓存请求的处理流程。借用网上的一张图来总结一下,图片原地址为Volley 源码解析
源码路径RequestQueue#start
/** * Starts the dispatchers in this queue. */ public void start() { // Make sure any currently running dispatchers are stopped. stop(); //缓存线程工作 // Create the cache dispatcher and start it. mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start(); //默认有4个网络线程工作 // 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(); } }
本篇文章我们就来详细了解一下两个线程调度器NetworkDispatcher和CacheDispatcher是如何工作的。
CacheDispatcher
顾名思义,这是一个缓存调度线程,用于处理走缓存的请求。首先看下它的变量。成员变量
/** 缓存请求队列 */ private final BlockingQueue<Request<?>> mCacheQueue; /** 网络请求队列 */ private final BlockingQueue<Request<?>> mNetworkQueue; /** 缓存类接口 */ private final Cache mCache; /** 返回处理请求的结果 */ private final ResponseDelivery mDelivery; /** 退出线程 */ private volatile boolean mQuit = false; /** 等待请求管理类或者处理重复请求的管理类*/ private final WaitingRequestManager mWaitingRequestManager;
接着进行初始化操作。
既然CacheDispatcher是一个线程,那么接着我们就来看下它的run方法。
@Override public void run() { if (DEBUG) VolleyLog.v("start new dispatcher"); //设置优先级,略低于正常线程的优先级 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //缓存线程初始化 mCache.initialize(); //循环工作 while (true) { try { processRequest(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } } } }
这里面没有什么大动作,我们来看下里面的processRequest方法是干嘛的。由于这个方法太长,我们一步一步分析。
首先从缓存队列中取出请求,判断是否已经取消了。
final Request<?> request = mCacheQueue.take(); request.addMarker("cache-queue-take"); // If the request has been canceled, don't bother dispatching it. if (request.isCanceled()) { request.finish("cache-discard-canceled"); return; }
接着从缓存中取出这个请求结果。如果不存在在这个请求结果的话,则加入到网络调度线程队列中去。
// Attempt to retrieve this item from cache. Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); // Cache miss; send off to the network dispatcher. if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) { mNetworkQueue.put(request); } return; }
如果存在这条缓存结果时,继续往下走,然后判断是否过期了。如果过期了则同样加入到网络线程队列中去。
// If it is completely expired, just send it to the network. if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) { mNetworkQueue.put(request); } return; }
接下来讲缓存的结果解析成response,
Response<?> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders));
接着判断是否需要刷新,不需要的话则直接返回缓存结果,否则加入到网络缓存队列中去。
if (!entry.refreshNeeded()) { //不需要刷新,直接返回结果 mDelivery.postResponse(request, response); } else { request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); // Mark the response as intermediate. response.intermediate = true; if (!mWaitingRequestManager.maybeAddToWaitingRequests(request)) { //添加到网络队列中去 mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(request); } catch (InterruptedException e) { // Restore the interrupted status Thread.currentThread().interrupt(); } } }); } else { mDelivery.postResponse(request, response); } }
这里面有个静态内部类WaitingRequestManager,我们来看下表示什么内容。
WaitingRequestManager
里面有个成员变量,说明表示存储重复请求的。private final Map<String, List<Request<?>>> mWaitingRequests = new HashMap<>();
接着我们看上面用的方法maybeAddToWaitingRequests,字面意思就是可能需要保存到等待请求队列中去。
if (mWaitingRequests.containsKey(cacheKey)) { // There is already a request in flight. Queue up. List<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey); if (stagedRequests == null) { stagedRequests = new ArrayList<Request<?>>(); } request.addMarker("waiting-for-response"); stagedRequests.add(request); mWaitingRequests.put(cacheKey, stagedRequests); if (VolleyLog.DEBUG) { VolleyLog.d("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); } return true; } else { // Insert 'null' queue for this cacheKey, indicating there is now a request in // flight. mWaitingRequests.put(cacheKey, null); request.setNetworkRequestCompleteListener(this); if (VolleyLog.DEBUG) { VolleyLog.d("new request, sending to network %s", cacheKey); } return false; }
首先判断这个集合中是否存在当前请求,如果存在的话则表示重复请求,则需要排队等待。
以上便是整个缓存请求的处理流程。借用网上的一张图来总结一下,图片原地址为Volley 源码解析
相关文章推荐
- android网络请求框架的学习之路——浅谈对Volley,OkHttp,Retrofit的了解与对比
- Android学习记录20171023--Volley网络框架(一)
- android网络框架volley学习之Volley类
- Android网络框架volley学习(十)分发结果ResponseDelivery简析
- android网络请求框架的学习之路——浅谈对Volley,OkHttp,Retrofit的了解与对比
- android网络请求框架的学习之路——浅谈对Volley,OkHttp,Retrofit的了解与对比 标签: androidVolleyOkhttpRetrofit网络请求框架
- android网络框架volley学习之HttpStack接口
- Android网络框架volley学习(九)请求结果Response<T>简析
- Android 网络通信框架Volley学习
- android网络框架volley学习之RequestQueue类
- Android网络通信框架Volley的学习笔记
- Android网络框架volley学习(十一)volley源码解析总结
- Android学习记录之Volley网络通信框架基础解析(1)
- android Volley网络通信框架学习
- Android网络框架volley学习(五)请求队列RequestQueue简析
- Android网络框架volley学习(八)缓存Cache简析
- Android网络框架volley学习(二)工作流程分析
- Android中Http网络请求库框架Volley和Asnyc-http的使用---第三方库学习笔记(一)
- android网络框架volley学习之基本数据类
- Android网络框架volley学习(一)基本用法