4

问题:我有 X 数量的 ImageView,我正在像这样动态添加:

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 或将实际位图作为字节数组传递。

问题:如何获取 Uri 或我使用 Volley ImageLoader 下载的实际位图。LruCache 我正在使用我在这里找到的 BitmapLruCache:Android Volley ImageLoader - BitmapLruCache parameter? . 有人可以帮助我解决这个问题或任何想法来实现我的目标。

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

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

图像不加载。我希望能够操纵图像,例如在将内容传递给下一个活动之前调整其大小。

4

2 回答 2

5

Volley 取决于您对缓存的实现,以实现成功的高效缓存。接收的构造函数ImageLoaderImageCacheVolley 中用于保存和加载位图的简单接口。

public ImageLoader(RequestQueue queue, ImageCache imageCache)

来自ImageCache接口的Javadoc的引用:

简单的缓存适配器接口。如果提供给 ImageLoader,它将在分派给 Volley 之前用作 L1 缓存。实现不得阻塞。建议使用 LruCache 实现。

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

您说它不起作用,也许您的实现没有针对您的用例进行优化。你用的是什么类型的缓存?你有一个集中式的RequestQueue并且ImageLoader是 Volley 团队推荐的吗?

看看这个问题,它与您的问题不完全相同,但可能对您有所帮助。它有一个简单的 LRU 缓存实现。

希望有帮助!

编辑:

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

现在,如果您想操作位图,您有几个选择,最好的 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() 将非空。

  2. 网络响应返回后,只会出现以下情况之一:

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

      或者

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

于 2013-07-29T15:19:29.610 回答
1

目前在 volley 中存在一个错误(我 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 作为参数传递给打开事物的活动。该解决方案具有令人羡慕的特性,如果在启动活动和显示位图之间出现问题并且图像发生问题,您仍将重新下载它并且一切都会正常工作。这可能永远不会/很少发生,但很高兴知道正确性得以保留。

于 2013-07-29T18:25:23.867 回答