性能优化

Volley缓存策略

2017-01-17  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读