之前根据 Volley 的工作流程大致解析了它的框架,接下来继续分析 Volley 的缓存机制,下面我在解析其缓存机制的同时也讲述一下个人对缓存生存时间的扩展.
缓存调度器的处理流程
要明白 Volley 的缓存机制,关键在于分析缓存调度器处理请求的过程,下面是我画的流程图:
这张流程图主要对应 CacheDispatcher 的 run 方法,首先根据 cachekey 查找缓存,如果没有缓存就把请求放到网络等待队列中,缓存调度器继续处理下一个请求;如果有缓存,但是缓存已经过期了,也将请求放到网络等待队列中并处理下一个请求,如果缓存没有过期,继续判断缓存是否需要刷新;如果不需要更新缓存,则直接传递解析后的缓存数据到主线程,如果需要更新缓存,则在传递解析后的缓存数据到主线程之后还会把请求添加到网络等待队列。
下面再看下流程中的两个关键的方法的源码:
|
|
从上面的代码中可以看出 ttl 就是缓存的生存时间,如果当前时间大于这个时间,缓存就过期,需要重新从网络请求数据。而 softTtl 代表软生存时间,过了这个时间缓存没有完全过期,可以返回给主线程,但是需要从网络请求新的数据刷新缓存.
Response 数据转换为缓存的逻辑
网络调度器成功请求到服务器数据后,会调用HttpHeaderParser
的静态方法parseCacheHeaders
解析成缓存。大致的逻辑如下:
a. 如果 Header 的 Cache-Control 字段中有no-cache
或no-store
字段,则返回 null
b. 否则根据 Cache-Control 和 Expires 首部,计算 ttl 和 softTtl
c. 根据 Date 首部,获得服务器响应时间
d. 根据其他信息,生成缓存其他信息
缓存逻辑的扩展
上面解析 response 数据为缓存在请求的shouldCache
为 false 的时候是可以不需要转换的,但是网络调度器现在的逻辑是先解析 response 数据并转换缓存,再判断shouldCache
和缓存是否为空,若需要缓存且缓存不为空才会写入缓存。所以这个地方可以做个小小的优化.
另外在使用 volley 的过程中,例如图片请求,如果服务器返回的 Header 的 Cache-Control 字段中有no-cache
或no-store
字段,或者没有 Expires 首部,就是出现缓存为空的或者 ttl 为 0 的情况。这样的话每次都要去重新请求图片,但是实际上这是不必要的,另外有些服务器返回的 Header 不规范也会出现这个问题。所以我觉得应该在这个时候使用默认的缓存生存时间,这样就可以避免这个问题,也方便客户端自己做一些缓存的控制。
扩展方法是在Request
类中加上 defaultTtl 和 defaultSoftTtl 两个属性,并改写解析成缓存的方法,下面是我改写后的parseCacheHeaders
方法:
|
|
这篇文章就分析缓存的一些处理逻辑,下篇文章讲述一下使用DiskLruCache
作为磁盘缓存.