使用Volley library的NetworkImageView是处理从网络显示图像的便捷方式.
问题
使用它可以获得的一个问题是它不能以内存有效的方式解码来自Web的图像.
这意味着如果你在其中使用带有多个NetworkImageView的gridView,并且每个都显示一个具有未知分辨率的图像(可能很小,可能很大),那么你最终会得到一个OOM.
例如,您可以将此对象的url设置为this one,并自己查看应用程序在显示位图后使用了多少内存,与之前使用的内容相比.
这个问题
我如何修改NetworkImageView解码位图的方式?
我可以改变它的一种方法是使其解码位图,同时将其缩小到所需的大小(或至少将其最大值设置为屏幕大小),例如使用this method缩减.
解决方法
>停止使用NetworkImageView.使用常规ImageView并实现侦听器以在可用时应用图像.这是第2步的先决条件.将NetworkImageView与get()方法一起使用可能会导致我的体验出现问题.
>创建一个ImageLoader并使用接收ImageRequest的get()方法.如果可以,请使用可选的构造函数,该构造函数将maxHeight和maxWidth作为参数.
>当您在ImageLoader中使用前面提到的get()方法时,保存该方法返回的ImageContainer引用,这样,如果视图在请求完成之前被回收,您将能够取消请求.
>在ImageLoader构造函数中为ImageCache提供良好的实现.这将降低解码已经可用的位图的冗余度.
>如果您的架构允许,请尝试在位图上使用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());
假设ViewHolder模式和imageContainer是ViewHolder类的成员,(3)的代码片段.主体适用于任何架构.
// 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);
默认的图像加载器(你可以在这里做):
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()); } } }