使用NetworkImageView(Volley库)时的OOM

and*_*per 7 android bitmap out-of-memory android-volley networkimageview

背景

使用Volley库NetworkImageView是处理从Web显示图像的便捷方式.

但是,它有一些错误(正如我在这里写的).

问题

使用它可以获得的一个问题是它不能以内存有效的方式解码来自Web的图像.

这意味着,如果您使用的是多NetworkImageView一个gridview,每个显示,有一个未知的分辨率(可能是小的,可能是大)的图像,你会最终有一个OOM.

作为一个例子,你可以把这个对象的URL是这一个,看看自己的应用中展示的位图,相比之前使用了多少后使用的内存.

这个问题

如何修改NetworkImageView解码位图的方式?

我可以改变它的一种方法是使在使用它下调到所需要的尺寸(或至少设置它的最大屏幕尺寸),例如,它解码位图这个方法缩小的.

Ita*_*ski 16

Volley有一个内置的方法,可以像你提到的那样将图像拟合到给定的宽度和高度.您需要停止使用方便的方法来加载NetworkImageView不使用它的图像.我建议使用以下方法来减少OOM错误的机会:

  1. 停止使用NetworkImageView.使用常规ImageView并实现侦听器以在可用时应用图像.这是第2步中使用的先决条件NetworkImageViewget()方法可能会导致我的experience`问题.
  2. 创建ImageLoader并使用get()接收的方法ImageRequest.如果可以,请使用可选的构造函数,该构造函数将maxHeightmaxWidth作为参数.
  3. 当您使用前面提到的get()方法时ImageLoader,保存ImageContainer方法返回的引用,这样如果视图在请求完成之前被回收,您将能够取消请求.
  4. 为构造函数ImageCache中的a提供良好的实现ImageLoader.这将降低解码已经可用的位图的冗余度.
  5. 如果您的架构允许,请尝试recycle()在位图上使用该方法,但请注意不要回收您可能仍需要的方法.

编辑:添加了代码示例

(2)+(4)的代码片段

// assuming sRequestQueue is your static global request queue 
// and `BitmapCache` is a good implementation for the `ImageCache` interface
sImageLoader = new ImageLoader(sRequestQueue, new BitmapCache());
Run Code Online (Sandbox Code Playgroud)

代码片段(3)假设ViewHolder模式并且imageContainerViewHolder该类的成员.主体适用于任何架构.

// when applying a new view cancel the previous request first

if (imageContainer != null) {
    imageContainer.cancelRequest();
}

// calculate the max height and max width

imageContainer = sImageLoader.get(imageUrl, 
    new DefaultImageListener(image), maxWidth, maxHeight);
Run Code Online (Sandbox Code Playgroud)

默认的图像加载器(你可以在这里做):

private class DefaultImageListener implements ImageListener {
    private ImageView imageView;

    public DefaultImageListener(ImageView view) {
        imageView = view
    }

    @Override
    public void onErrorResponse(VolleyError error) {
        //handle errors
    }

    @Override
    public void onResponse(ImageContainer response, boolean isImmediate) {
        if (response.getBitmap() != null) {
            imageView.setImageBitmap(response.getBitmap());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)