美文网首页性能优化
Volley缓存策略

Volley缓存策略

作者: 小范屯 | 来源:发表于2017-01-17 17:07 被阅读53次

    使用分析的库为:com.mcxiaoke.volley:library:1.0.19

    0.如果开启缓存(默认为开启)

    //Request.java
    
    /** Whether or not responses to this request should be cached. */
    private boolean mShouldCache = true;
    
    /**
     * Set whether or not responses to this request should be cached.
     *
     * @return This Request object to allow for chaining.
     */
    public final Request<?> setShouldCache(boolean shouldCache) {
        mShouldCache = shouldCache;
        return this;
    }
    

    1. 获取Cache.Entry,如果为null,就请求网络

    //CacheDispatcher.java
    
    Cache.Entry entry = mCache.get(request.getCacheKey());
    

    2. 判断缓存是否过期,如果过期就就请求网络

    //CacheDispatcher.java
    
    // 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;
    }
    
    /** True if the entry is expired. */
    public boolean isExpired() {
        return this.ttl < System.currentTimeMillis();
    }
    
    public long getTtl(){
        long ttl;
        if (hasCacheControl()){
            softExpire = now + maxAge * 1000;
            ttl = mustRevalidate ? softExpire : softExpire + staleWhileRevalidate * 1000;
        } else {
            ttl = now + (serverExpires - serverDate);
        }
        return ttl;
    }
    
    public boolean hasCacheControl(){
        String headerValue = headers.get("Cache-Control");
        boolean hasCacheControl = headerValue != null;
        return hasCacheControl;
    }
    /*softExpire和softTtl是一样的*/
    public long getSoftTtl(){
        boolean softExpire = hasCacheControl() ? now + maxAge * 1000 : now + (serverExpires - serverDate);
        return softExpire;
    }
    

    3. 判断是否需要刷新,不需要刷新,则直接返回缓存的数据;

    如果需要刷新,则先返回缓存数据,再次请求网络

    //CacheDispatcher.java
    
    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.
        final Request<?> finalRequest = request;
        mDelivery.postResponse(request, response, new Runnable() {
            @Override
            public void run() {
                try {
                    mNetworkQueue.put(finalRequest);
                } catch (InterruptedException e) {
                    // Not much we can do about this.
                }
            }
        });
    }
    
    /** True if a refresh is needed from the original data    source. */
    public boolean refreshNeeded() {
        return this.softTtl < System.currentTimeMillis();
    }
    /*softExpire和softTtl是一样的*/
    public long getSoftTtl(){
        boolean softExpire = hasCacheControl() ? now + maxAge * 1000 : now + (serverExpires - serverDate);
        return softExpire;
    }
    

    4.如果的响应的statusCode为304,并且已经从本地缓存数据callback一次了,则忽略这个请求(不进行callback),否则,继续解析解析网络数据,并且返回(这就会出现回调两次callback的情况)。

    //NetworkDispatcher.java
    
    // If the server returned 304 AND we delivered a response already,
    // we're done -- don't deliver a second identical response.
    if (networkResponse.notModified && request.hasHadResponseDelivered()) {
        request.finish("not-modified");
        continue;
    }
    

    补充:
    那服务端如何判断304的呢?
    就需要先添加两个请求头
    If-None-Match(从上次的响应头ETag获取)
    If-Modified-Since(从上次的响应头Last-Modified获取)

    5.最后,如果请求使用缓存,则把获取的网络数据,保存到本地。

    //NetworkDispatcher.java
    
    // Write to cache if applicable.
    // TODO: Only update cache metadata instead of entire record for 304s.
    if (request.shouldCache() && response.cacheEntry != null) {
        mCache.put(request.getCacheKey(), response.cacheEntry);
        request.addMarker("network-cache-written");
    }
    

    附一手写的图,来理解ttl和softttl的关系

    WechatIMG1.jpeg

    相关文章

      网友评论

        本文标题:Volley缓存策略

        本文链接:https://www.haomeiwen.com/subject/zqombttx.html