Volley框架的基本解读(五)
来源:互联网 发布:网络著作权侵权 编辑:程序博客网 时间:2024/06/07 06:54
在之前四篇博客中,我们已经将RequestQueue中start方法中的网络请求这条主线完全解析了一遍,接下来我们看另一条缓存主线,CacheDispatcher的源码:
public class CacheDispatcher extends Thread
同NetworkDispatcher一样,CacheDispatcher同样是一个线程
public CacheDispatcher( BlockingQueue<Request> cacheQueue, BlockingQueue<Request> networkQueue, Cache cache, ResponseDelivery delivery) { mCacheQueue = cacheQueue; mNetworkQueue = networkQueue; mCache = cache; mDelivery = delivery; }
里面也只有一个构造方法,四个参数分别是缓存队列,网络队列,缓存处理类,结果分发类,同样的在RequestQueue调用了它的start方法,因为是Thread所以我们看run方法:
@Override public void run() { if (DEBUG) VolleyLog.v("start new dispatcher"); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // Make a blocking call to initialize the cache. // 将缓存数据读入内存 mCache.initialize(); while (true) { try { // Get a request from the cache triage queue, blocking until // at least one is available. // 从缓存队列中取出request final Request request = mCacheQueue.take(); // 调试信息 request.addMarker("cache-queue-take"); // If the request has been canceled, don't bother dispatching it. // 如果该request以取消,则中断任务 if (request.isCanceled()) { request.finish("cache-discard-canceled"); continue; } // 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. mNetworkQueue.put(request); continue; } // If it is completely expired, just send it to the network. // 如果缓存过期,加入网络队列 if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); mNetworkQueue.put(request); continue; } // We have a cache hit; parse its data for delivery back to the request. // 命中缓存,交由request解析,并输出调试日志 request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); // 这里再次判断缓存过期,我的理解是异步处理,可能导致过程中缓存过期 if (!entry.refreshNeeded()) { // Completely unexpired cache hit. Just deliver the response. // 命中缓存,分发事件 mDelivery.postResponse(request, response); } else { // Soft-expired cache hit. We can deliver the cached response, // but we need to also send the request to the network for // refreshing. // 命中过期缓存,分发结果,并向网络请求一次 request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); // Mark the response as intermediate. response.intermediate = true; // Post the intermediate response back to the user and have // the delivery then forward the request along to the network. mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(request); } catch (InterruptedException e) { // Not much we can do about this. } } }); } } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. // 程序可能会中断,因为这个时候是该放弃了 if (mQuit) { return; } continue; } } }
该方法首先初始化了缓存数据,让我们进入mCache.initialize方法里面看看,这里说一点Cache同Network一样是一个接口,里面的方法稍微多一点,我们来看具体子类实现,同样是在Volley.newRequestQueue中创建的:
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
public DiskBasedCache(File rootDirectory) { this(rootDirectory, DEFAULT_DISK_USAGE_BYTES); }
public DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes) { mRootDirectory = rootDirectory; mMaxCacheSizeInBytes = maxCacheSizeInBytes; }
rootDirectory是缓存径路,DEFAULT_DISK_USAGE_BYTES默认值是5 * 1024 * 1024,也就是5M,表示最大缓存容量。
我们来看看它的initialize方法:
/** * Initializes the DiskBasedCache by scanning for all files currently in the * specified root directory. Creates the root directory if necessary. * * 初始化缓存,将缓存文件全部读入内存中 */ @Override public synchronized void initialize() { // 如果文件不存在,说明无缓存 if (!mRootDirectory.exists()) { if (!mRootDirectory.mkdirs()) { VolleyLog.e("Unable to create cache dir %s", mRootDirectory.getAbsolutePath()); } return; } // 获取缓存文件数组 File[] files = mRootDirectory.listFiles(); if (files == null) { return; } for (File file : files) { FileInputStream fis = null; try { fis = new FileInputStream(file); CacheHeader entry = CacheHeader.readHeader(fis); entry.size = file.length(); putEntry(entry.key, entry); } catch (IOException e) { if (file != null) { file.delete(); } } finally { try { if (fis != null) { fis.close(); } } catch (IOException ignored) { } } } }
前面很简单,判断缓存路径是否存在,否创建缓存路径,如果创建失败,那么初始化也就失败了。
然后获取缓存路径下的所有缓存文件,用字节流读取解析,CacheHeader是DiskBasedCache中的静态内部类,里面定义了很多字段,比如size数据长度,key缓存的键,其实就是URL,还有serverDate服务器的返回时间等等,readHeader方法就是对读取缓存文件进行了封装,考虑到涉及到的方法太多,我就不一一贴出来了,得到了CacheHeader这个缓存实体,putEntry方法就是将它放入内存:
/** * Puts the entry with the specified key into the cache. * @param key The key to identify the entry by. * @param entry The entry to cache. * * 将缓存读入内存 */ private void putEntry(String key, CacheHeader entry) { // 如果内存中没有该缓存,累加当前缓存大小,如果存在,计算缓存容量差,再进行累计 if (!mEntries.containsKey(key)) { mTotalSize += entry.size; } else { CacheHeader oldEntry = mEntries.get(key); mTotalSize += (entry.size - oldEntry.size); } mEntries.put(key, entry); }
mEntries是一个Map集合,定义在DiskBasedCache的成员变量中
/** Map of the Key, CacheHeader pairs 初始位16,扩展0.75倍,使用排序*/ private final Map<String, CacheHeader> mEntries = new LinkedHashMap<String, CacheHeader>(16, .75f, true);
initialize方法我们分析完了,回过头继续看CacheDispatcher的run方法,同NetworkDispatcher一样的写法,后面也是一个while死循环,mCacheQueue同样是一个优先级队列,试图从队列中获取一个request,判断request是否取消,是结束该次请求,request.getCacheKey()返回的就是URL,试图从缓存中查找对应的缓存,如果找不到,扔进网络队列中,它就不管了,如果获取到的缓存已经过期,还是扔进网络队列,当个甩手掌柜,到这里可以确定缓存有效,封装成Response准备返回,下面这个!entry.refreshNeeded()对缓存过期的再次判断,是我也不太理解的地方,但代码是很清晰的,如果没有过期,分发结果,如果过期了,它依然会返回结果,但会向网络请求一次,也就是说,该request会得到两个response,一个是缓存的,一个是网络的。
到这里大家可能已经急不可待想揭开mDelivery的神秘面纱了,但我们下一篇再说,在CacheDispatcher还有一个我们熟悉的方法:
/** * Forces this dispatcher to quit immediately. If any requests are still in * the queue, they are not guaranteed to be processed. * * 标记退出,并中断线程 */ public void quit() { mQuit = true; interrupt(); }
作用就不必我多说了吧,我们下篇博客再见!
0 0
- Volley框架的基本解读(五)
- Volley框架的基本解读(一)
- Volley框架的基本解读(二)
- Volley框架的基本解读(三)
- Volley框架的基本解读(四)
- Volley框架的基本解读(六)
- Volley框架的基本解读(七)
- Volley框架的基本解读(八)
- volley框架的解读
- Volley的框架解读五(网络调度NetworkDispatcher)
- Volley的框架解读准备一HttpURLConnection
- Volley的框架解读七(Request)
- Volley框架的基本使用方法
- Volley框架的基本使用方法
- Volley===Volley框架的基本使用方法
- Volley===Volley框架的基本使用方法
- Android Volley网络框架的基本使用
- 开源框架--Volley的基本应用
- ANR基础
- ROC曲线的绘制
- Dubbo入门
- oracle查看当前用户权限
- Firebug学习笔记
- Volley框架的基本解读(五)
- java中instanceof用法
- 亚马逊Kindle强势掌控电子书市场 竞争对手一个接一个关闭业务
- Android Bluetooth 4.0深入学习
- php 计算两个日期的间隔天数
- 【iOS开发基础教程】C语言if语句的用法
- 前端开发:模块化 — 高效重构
- 测试方法分类
- STM32F10x工程模板 附带工程模板使用说明及各文件简单介绍