6

我正在尝试显示包含大量(远程)图像的列表视图。我正在尝试使用 volley 来完成这项任务。

Volley 有点效果,但还不够好。在 ImageLoader.get volley 中有如下一段代码:

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

然而,getCacheKey 会产生一个像这样的键:

/**
 * 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();
}

即它将一些“元数据”如宽度和高度附加到键。

这个键永远不会产生命中,如果图像不在 L1 缓存中,它会在线获取。当在线获取图像时,它会保存在磁盘缓存中,但 Volley 将其保存为 URL(并且只有 URL)作为键。

这是预期的行为吗?我错过了什么吗?

4

6 回答 6

9

您没有得到任何点击的原因是因为 Volley 中用于磁盘缓存的默认行为取决于您请求的元素的 HTTP 标头(在您的情况下是图像)。

Volley 的工作方式是:

  1. ImageLoader检查图像的 L1 缓存(您ImageLoader在其构造函数中提供的内存缓存)。如果可用返回图像。
  2. 请求由 处理RequestQueue。它检查图像的 L2(磁盘缓存)。
  3. 如果在磁盘缓存中找到,请检查映像过期时间。如果没有过期,退货。
  4. 下载图像并返回。
  5. 将图像保存在缓存中。

如果您希望默认设置正常工作,图像必须有一个Cache-Control标题,如 max-age=???问号表示从下载时间开始的足够秒数。

如果您想更改默认行为,我不确定,但我认为您必须稍微编辑代码。

查看CacheDispatcherVolley 源代码中的类。

于 2013-07-31T13:32:15.893 回答
1

您可以发布实现 ImageCache 的类吗?

我自己一直在看这个,并在我的代码中意识到,当它从磁盘加载位图时,我没有将位图添加到内存缓存中,所以每次它总是会从磁盘重新加载它。

这是一个简单的例子,说明了我的意思以及我哪里出错了

@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;
    }
于 2013-07-23T14:43:07.023 回答
1

我今天在自己的应用程序中找到了这个问题。我在构造函数中设置了以 KB 为单位的最大缓存大小,但在 sizeOf() 中报告了以字节为单位的大小,因此没有缓存任何内容。

这个答案让我直截了当。

于 2013-10-02T22:07:26.013 回答
1

可能您正在使用 NetworkImageView 加载图像。你可以使用 ImageView 和 ImageLoader 来做同样的事情。使用 ImageLoader,键中的元数据对于任何图像大小都类似于“#W0#H0”。

ImageLoader imageLoader = getImageLoader();
imageLoader.get(url, ImageLoader.getImageListener(imageView, defaultDrawable, errorDrawable));
于 2015-08-25T20:25:56.633 回答
0

如果响应标头中未设置缓存控制,Volley 不会缓存任何内容。

检查 Volley 中的HttpHeaderParser类实现。

缓存可以基于 max-age 或 E-tag。检查您的响应标头并确定那里设置的任何内容。它看起来像这样。

Cache-Control → public, max-age=300

缓存头信息

于 2015-04-02T14:07:55.163 回答
-1

这是您希望它工作的确切方式。

  1. 点击 url 并在它不可用时获取图像。
  2. 如果可用,从缓存中加载图像。
于 2013-07-15T07:16:23.997 回答