Volley

来源:互联网 发布:云计算java工程师招聘 编辑:程序博客网 时间:2024/05/17 07:33

Volley的核心 是两个队列 :CacheQueue和NetworkQueue;
Request先添加到CacheQueue里,然后被CacheDispatcher轮询,查到如果有缓存,就直接解析出respons对象,没有哦就添加到NetworkQueue中,被NetworkDispathcer轮询,**默认有4个NetworkDisatcher来轮询**NetworkQueue,每个Dispathcer都是 一个线程,
所以main thread, cache thread 和4个network thread

其中的两个Queue,都是一个BlockingQueue
这是BlockingQueue的特性 是:如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒,同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间时才会被唤醒继续操作。

网络执行单元,Volley提供了httpStack接口,并提供了HurlStack和HurlClientStack两个实现类,(此处就是开放性接口,比如可以接入okHttpStack)

缺陷: 1.缓存依靠服务器协议,不保准
2.get和post请求方式需要封装,加个单例
3.要过滤重复请求
4.ImageLoader没做缓存,只有接口

缓存

Volley的缓存是基于标准的http协议的,也就是在请求头中相关缓存的信息,比如:
expires字段:缓存的过期时间
Cache-Control 字段:控制是否有缓存或者是否需要先验证等
Last-Modified : 最后修改时间

所以,Volley缓存处 的关键源码:

public static Cache.Entry parseCacheHeaders(NetworkResponse response) {    long now = System.currentTimeMillis();    Map headers = response.headers;    long serverDate = 0;    long lastModified = 0;    long serverExpires = 0;    long softExpire = 0;    long finalExpire = 0;    long maxAge = 0;    long staleWhileRevalidate = 0;    boolean hasCacheControl = false;    boolean mustRevalidate = false;    String serverEtag;    String headerValue;    headerValue = headers.get("Date");    if (headerValue != null) {        serverDate = parseDateAsEpoch(headerValue);    }    // 获取响应体的Cache缓存策略.    headerValue = headers.get("Cache-Control");    if (headerValue != null) {        hasCacheControl = true;        String[] tokens = headerValue.split(",");        for (String token : tokens) {            token = token.trim();            if (token.equals("no-cache") || token.equals("no-store")) {                // no-cache|no-store代表服务器禁止客户端缓存,每次需要重新发送HTTP请求                return null;            } else if (token.startsWith("max-age=")) {                // 获取缓存的有效时间                try {                    maxAge = Long.parseLong(token.substring(8));                } catch (Exception e) {                    maxAge = 0;                }            } else if (token.startsWith("stale-while-revalidate=")) {                try {                    staleWhileRevalidate = Long.parseLong(token.substring(23));                } catch (Exception e) {                    staleWhileRevalidate = 0;                }            } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {                // 需要进行新鲜度验证                mustRevalidate = true;            }        }    }    // 获取服务器资源的过期时间    headerValue = headers.get("Expires");    if (headerValue != null) {        serverExpires = parseDateAsEpoch(headerValue);    }    // 获取服务器资源最后一次的修改时间    headerValue = headers.get("Last-Modified");    if (headerValue != null) {        lastModified = parseDateAsEpoch(headerValue);    }    // 获取服务器资源标识    serverEtag = headers.get("ETag");    // 计算缓存的ttl和softTtl    if (hasCacheControl) {        softExpire = now + maxAge * 1000;        finalExpire = mustRevalidate                ? softExpire                : softExpire + staleWhileRevalidate * 1000;    } else if (serverDate > 0 && serverExpires >= serverDate) {        // Default semantic for Expire header in HTTP specification is softExpire.        softExpire = now + (serverExpires - serverDate);        finalExpire = softExpire;    }    Cache.Entry entry = new Cache.Entry();    entry.data = response.data;    entry.etag = serverEtag;    entry.softTtl = softExpire;    entry.ttl = finalExpire;    entry.serverDate = serverDate;    entry.lastModified = lastModified;    entry.responseHeaders = headers;    return entry;}

显然,就是获取了Cache-Control值,判断是否缓存,在获取时间,判断是否过期,然后用一个entry 存储相关信息。

注意事项

在面板被finish掉的时候(比如onStop方法),要调用
requestQueue.canceAll( tag ), 此处的Tag是你的request在加入队列之前,setTag设置的, 所以是取消相同tag的所以请求。
取消后 ,onResponse不会被执行。

0 0
原创粉丝点击