public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
   Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
   if (entry == null) {
     entry = new Cache.Entry();
     entry.data = response.data;
   }
   return entry;
 }
  @Test
  public void testCachePutExpired() throws VolleyError {
    when(cacheEntry.isExpired()).thenReturn(true);

    // mock non expired entry for return
    Cache.Entry networkEntry = mock(Cache.Entry.class);
    when(networkEntry.isExpired()).thenReturn(true);

    Response response = Response.success(null, networkEntry);
    when(request.parseNetworkResponse(any(NetworkResponse.class))).thenReturn(response);

    dispatcher.processRequest(request);
    verify(cache, never()).put("test-cache-key", networkEntry);
  }
 /**
  * Extracts a {@link com.android.volley.Cache.Entry} from a {@link
  * com.android.volley.NetworkResponse}.
  *
  * @param response The network response to parse headers from
  * @param cacheTime 缓存时间,如果设置了这个值,不管服务器返回是否可以缓存,都会缓存,一天为1000*60*60*24
  * @return a cache entry for the given response, or null if the response is not cacheable.
  */
 public static Cache.Entry parseCacheHeaders(NetworkResponse response, long cacheTime) {
   long now = System.currentTimeMillis();
   long softExpire = now + cacheTime;
   Cache.Entry entry = parseCacheHeaders(response);
   if (null == entry && response.data.length > 0) {
     entry = new Cache.Entry();
     entry.data = response.data;
     entry.serverDate = now;
     // Time to Leave 客户端可以通过这个数据来判断当前内容是否过期。
     entry.ttl = softExpire;
     // 在这个时间内,是否需要刷新
     entry.softTtl = softExpire;
   }
   return entry;
 }
  @Test
  public void testRefresh() throws VolleyError {
    when(cacheEntry.isExpired()).thenReturn(false);
    when(cacheEntry.refreshNeeded()).thenReturn(true);

    // mock non expired entry for return
    Cache.Entry networkEntry = mock(Cache.Entry.class);
    when(networkEntry.isExpired()).thenReturn(false);

    Response response = Response.success(null, networkEntry);
    when(request.parseNetworkResponse(any(NetworkResponse.class))).thenReturn(response);
    request.setShouldCache(true);

    dispatcher.processRequest(request);
    verify(cache).put("test-cache-key", networkEntry);
    verify(mockNetwork).performRequest(request);
  }
  public static Cache.Entry parseIgnoreCacheHeaders(
      NetworkResponse response, String url, long softttl, long hardttl) {
    long now = System.currentTimeMillis();

    Map<String, String> headers = response.headers;
    long serverDate = 0;
    String serverEtag = null;
    String headerValue;
    headerValue = headers.get("Date");
    if (headerValue != null) {
      serverDate = parseDateAsEpoch(headerValue);
    }

    serverEtag = headers.get("ETag");

    // entry expires
    // completely
    final long softExpire = now + softttl;
    final long ttl = now + hardttl;

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = ttl;
    entry.serverDate = serverDate;
    entry.responseHeaders = headers;

    return entry;
  }
Exemple #6
0
  /**
   * Extracts a {@link Cache.Entry} from a {@link com.android.volley.NetworkResponse}. Cache-control
   * headers are ignored. SoftTtl == 3 mins, ttl == 24 hours.
   *
   * @param response The network response to parse headers from
   * @return a cache entry for the given response, or null if the response is not cacheable.
   */
  public static Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response) {
    long now = System.currentTimeMillis();

    Map<String, String> headers = response.headers;
    long serverDate = 0;
    String serverEtag = null;
    String headerValue;

    headerValue = headers.get("Date");
    if (headerValue != null) {
      serverDate = com.android.volley.toolbox.HttpHeaderParser.parseDateAsEpoch(headerValue);
    }

    serverEtag = headers.get("ETag");

    final long cacheHitButRefreshed =
        3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
    final long cacheExpired =
        24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
    final long softExpire = now + cacheHitButRefreshed;
    final long ttl = now + cacheExpired;

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = ttl;
    entry.serverDate = serverDate;
    entry.responseHeaders = headers;

    return entry;
  }
  @Test
  public void testCachePut() throws VolleyError {
    // Given
    when(cacheEntry.isExpired()).thenReturn(true);

    // mock non expired entry for return
    Cache.Entry networkEntry = new Cache.Entry();
    networkEntry.ttl = System.currentTimeMillis() + 100000;

    NetworkResponse networkResponse = mock(NetworkResponse.class);
    when(mockNetwork.performRequest(any(Request.class))).thenReturn(networkResponse);

    Response response = Response.success(new Object(), networkEntry);
    when(request.parseNetworkResponse(any(NetworkResponse.class))).thenReturn(response);
    request.setShouldCache(true);

    // When
    dispatcher.processRequest(request);

    // Then
    verify(cache).put("test-cache-key", networkEntry);
  }
  @Override
  public void run() {
    if (DEBUG) {
      VolleyLog.v("start new dispatcher");
    }
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    // Make a blocking call to initialize the cache.
    mCache.initialize();
    while (true) {
      try {
        // Get a request from the cache triage queue, blocking until at least one is available.
        final Request<?> request = mCacheQueue.take();
        request.addMarker("cache-queue-take");
        // If the request has been canceled, don't bother dispatching it.
        if (request.isCanceled()) {
          request.finish("cache-discard-canceled");
          continue;
        }

        // Attempt to retrieve this item from cache.
        Cache.Entry entry = mCache.get(request.getCacheKey());
        if (entry == null) {
          request.addMarker("cache-miss");
          // Cache miss; send off to the network dispatcher.
          mNetworkQueue.put(request);
          continue;
        }

        // 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;
        }

        // We have a cache hit; parse its data for delivery back to the request.
        request.addMarker("cache-hit");
        Response<?> response =
            request.parseNetworkResponse(
                new NetworkResponse(entry.data, entry.responseHeaders)); // TODO
        request.addMarker("cache-hit-parsed");

        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.
          mDelivery.postResponse(
              request,
              response,
              new Runnable() {
                @Override
                public void run() {
                  try {
                    mNetworkQueue.put(request);
                  } catch (InterruptedException e) {
                    // Not much we can do about this.
                  }
                }
              });
        }

      } catch (InterruptedException e) {
        // We may have been interrupted because it was time to quit.
        if (mQuit) {
          return;
        }
        continue;
      }
    }
  }
Exemple #9
0
  /**
   * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
   *
   * @param response The network response to parse headers from
   * @return a cache entry for the given response, or null if the response is not cacheable.
   */
  public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
    long now = System.currentTimeMillis();

    Map<String, String> headers = response.headers;

    long serverDate = 0;
    long serverExpires = 0;
    long softExpire = 0;
    long maxAge = 0;
    long lastModify = 0;
    boolean hasCacheControl = false;

    String serverEtag = null;
    String headerValue;

    headerValue = headers.get("Date");
    if (headerValue != null) {
      serverDate = parseDateAsEpoch(headerValue);
    }

    headerValue = headers.get("Cache-Control");
    if (headerValue != null) {
      hasCacheControl = true;
      String[] tokens = headerValue.split(",");
      for (int i = 0; i < tokens.length; i++) {
        String token = tokens[i].trim();
        if (token.equals("no-cache") || token.equals("no-store")) {
          return null;
        } else if (token.startsWith("max-age=")) {
          try {
            maxAge = Long.parseLong(token.substring(8));
          } catch (Exception e) {
          }
        } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
          maxAge = 0;
        }
      }
    }

    headerValue = headers.get("Expires");
    if (headerValue != null) {
      serverExpires = parseDateAsEpoch(headerValue);
    }

    serverEtag = headers.get("ETag");

    // Cache-Control takes precedence over an Expires header, even if both exist and Expires
    // is more restrictive.
    if (hasCacheControl) {
      softExpire = now + maxAge * 1000;
    } else if (serverDate > 0 && serverExpires >= serverDate) {
      // Default semantic for Expire header in HTTP specification is softExpire.
      softExpire = now + (serverExpires - serverDate);
    }

    headerValue = headers.get("Last-Modified");
    if (headerValue != null) {
      lastModify = parseDateAsEpoch(headerValue);
    }

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = entry.softTtl;
    entry.serverDate = serverDate;
    entry.lastModify = lastModify;
    entry.responseHeaders = headers;

    return entry;
  }
 @Test
 public void testNetworkAccess() throws VolleyError {
   when(cacheEntry.isExpired()).thenReturn(true);
   dispatcher.processRequest(request);
   verify(mockNetwork).performRequest(request);
 }