如何获取我使用Volley ImageLoader下载的缓存位图



问题:我有X数量的ImageViews,我正在动态添加,如下所示:

for (int i=2; i < result.size(); i++) {
        // instantiate image view
        ImageView mImageView = new ImageView(this);
        mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        mImageView.setBackgroundResource(R.drawable.selectable_background_theme);
        mImageView.setOnClickListener(this);
        // download image and display it
        mImageLoader.get(result.get(i), ImageLoader.getImageListener(mImageView, R.drawable.ic_logo, R.drawable.ic_action_refresh));
        // add images to container view
        mLlDescContent.addView(mImageView);
    }

希望能够点击图像并在另一个活动中全屏显示。我已经阅读了一些方法,例如传递Uri或将实际位图作为字节数组传递。

问题:如何获取我使用Volley ImageLoader下载的Uri或实际位图。我使用的LruCache是我在这里找到的BitmapLruCache:Android Volley ImageLoader-BitmapLruCache参数。有人能帮我实现这个目标吗。

我在上面的代码后尝试了这个,但什么都没有:

Bitmap mBitmap = VolleyInstance.getBitmapLruCache().getBitmap(result.get(2));
mIvAuthorImg.setImageBitmap(mBitmap);

编辑:如果我用重新请求图像

mImageLoader.get(result.get(i), ImageLoader.getImageListener(mImageView, R.drawable.ic_logo, R.drawable.ic_action_refresh));

图像是从缓存中加载的,但如果我尝试使用直接从缓存中访问图像

Bitmap mBitmap = VolleyInstance.getBitmapLruCache().getBitmap(result.get(2));
mIvAuthorImg.setImageBitmap(mBitmap);

图像不会加载。我希望能够处理图像,比如在将其传递给下一个活动之前调整一个东西的大小。

Volley依赖于缓存的实现来实现成功高效的缓存。ImageLoader的构造函数采用ImageCache,这是Volley中保存和加载位图的一个简单接口。

public ImageLoader(RequestQueue queue, ImageCache imageCache)

引用ImageCache接口的Javadoc:

简单的缓存适配器接口。如果提供给ImageLoader,它将在调度到Volley之前用作一级缓存。实现不能阻止。建议使用LruCache实现。

达尔文是对的。如果您请求一个图像,并且该图像存在于缓存中,则它将从缓存加载,而不是从web加载。这应该是您的情况,因为您正在加载并呈现一个图像,如果单击该图像,则应在新活动的缓存中显示该图像。

你说它不起作用,也许你的实现没有针对你的用例进行优化。你用的是哪种缓存?您是否有Volley团队推荐的集中式RequestQueueImageLoader

看看这个问题,它和你的问题不完全一样,但可能对你有帮助。它有一个简单的LRU缓存实现。

希望能有所帮助!

编辑:

Volley的重点不在于担心实现细节。你想要一张照片吗?它将以最好、最快的方式为您加载(从内存加载,如果不通过网络加载)。这正是你应该看待它的方式。检索缓存然后查看它不是正确的方法

现在,如果你想操作位图,你有几个选项,最好的IMO是实现你自己的Image Listener,将它传递给get()方法,而不是默认的方法。

类似这样的东西:

public class MyImageListener implements ImageListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        // handle errors
    }
    @Override
    public void onResponse(ImageContainer response, boolean isImmediate) {
        Bitmap bitmap = response.getBitmap();
        if (bitmap != null) {
            //                    
            // manipulations
            //
            // assuming mView is a reference to your ImageView
            mView.setImageBitmap(bitmap);
        } else {
            // display placeholder or whatever you want
        }
    }
}

来自Javadoc:

呼叫流程如下:

  1. 附加到请求后,将调用onResponse(response,true)来反映任何已可用的缓存数据。如果数据可用,response.getBitmap()将为非null。

  2. 在网络响应返回后,只会发生以下情况之一:

    • 如果加载了图像,将调用onResponse(response,false)。

    • 如果加载图像时出错,将调用onErrorResponse。

目前在volution中有一个错误(我70%确信这是一个错误),如果没有指定缓存过期(比如说,如果你从S3存储桶中获得一个具有永不过期设置的图像),你总是会从网络重新下载。

您可以通过检查HttpHeaderParser并将相关位(这并不完全疯狂,因为您无论如何都必须包含截击源代码)更改为:

// 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);
} else if (serverExpires == 0) {
    softExpire = Long.MAX_VALUE;
}

然后,您可以将Uri传递给活动,将其作为参数打开。该解决方案具有令人羡慕的特性,即如果在启动活动和显示位图之间图像出现问题,您仍然可以重新下载它,并且一切正常。这种情况可能永远不会/很少发生,但很高兴知道正确性得到了保留。