Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Volley and bitmap caching

I'm trying to display a listview with a lot of (remote) images. I'm trying to use volley for the task.

Volley somewhat works, but not good enough. In ImageLoader.get volley has the following piece of code:

    final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight);

    // Try to look up the request in the cache of remote images.
    Bitmap cachedBitmap = mCache.getBitmap(cacheKey);
    if (cachedBitmap != null) {
        // Return the cached bitmap.
        ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null);
        imageListener.onResponse(container, true);
        return container;
    }

However, getCacheKey produces a key like this:

/**
 * Creates a cache key for use with the L1 cache.
 * @param url The URL of the request.
 * @param maxWidth The max-width of the output.
 * @param maxHeight The max-height of the output.
 */
private static String getCacheKey(String url, int maxWidth, int maxHeight) {
    return new StringBuilder(url.length() + 12).append("#W").append(maxWidth)
            .append("#H").append(maxHeight).append(url).toString();
}

i.e. It appends some "metadata" like width and height to the key.

This key never produces a hit and if the image is not in the L1 cache it is fetched online. When the image is fetched online it is saved in the disk-cache but Volley saves it with the URL (and only the URL) as key.

Is this expected behaviour? Am I missing something?

like image 507
Markus Avatar asked Jul 15 '13 07:07

Markus


2 Answers

The reason you're not getting any hits is because the default behavior in Volley for disk caching is dependent on the HTTP headers of the element you're requesting (in your case, an image).

The way Volley works is:

  1. ImageLoader checks the L1 cache for image (memory cache provided by you to the ImageLoader in its constructor). If available return image.
  2. Request processed by RequestQueue. It checks the L2 (disk cache) for the image.
  3. If found in the disk cache, check the image expiry time. If not expired, return.
  4. Download image and return it.
  5. Save image in caches.

If you want the default settings to work, the images must have a Cache-Control header like max-age=??? where the question marks indicate enough seconds from the time it was downloaded.

If you want to change the default behavior, I'm not sure, but I think you have to edit the code a bit.

Look at the CacheDispatcher class in the Volley source.

like image 85
Itai Hanski Avatar answered Sep 18 '22 23:09

Itai Hanski


Can you post your class that implements ImageCache.

I've just been looking at this myself and realised in my code I wasn't adding the bitmap to the memory cache when it was loading it from the disk, so it would always reload it from the disk each time.

This is a simple example of what I mean and where I was going wrong

@Override
    public Bitmap getBitmap(String cachKey) {

        Bitmap b = null;

            //check the memory first
            b = memoryCache.get(cacheKey);
            if(b == null){
                //memory cache was null, check file cache           
                b = diskLruImageCache.getBitmap(cacheKey);

                // this is where it needs to be added to your memory cache
                if(b != null){
                    memoryCache.put(url, b);
                }
            }



        return b;
    }
like image 24
David Scott Avatar answered Sep 21 '22 23:09

David Scott