Volley

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值