15

在 Android 4.1 a 中,对我来说,我们的应用程序中出现了看似奇怪的错误。在应用程序中,扩展 BaseAdapter 的自定义适配器附加到 Gallery 小部件。当从左到右快速滚动时,反之亦然,我得到一个带有异常消息的 FC:

java.lang.IllegalArgumentException:无法绘制回收位图

getView(..) 方法的代码如下:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder;

    if (convertView == null){
        // View is not recycled. Inflate the layout.
        LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = vi.inflate(R.layout.gallery_image, parent, false);

        viewHolder = new ViewHolder();
        viewHolder.image = (ImageView) convertView.findViewById(R.id.gallery_image);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder)convertView.getTag();
        viewHolder.image.setImageDrawable(null);
    }

    imageLoader.displayImage(images.get(position).getFilename(),
            images.get(position).getUrlThumbnail(),
            viewHolder.image,
            Math.round(BitmapUtil.convertDpToPixel(400f, context)),
            Math.round(BitmapUtil.convertDpToPixel(400f, context)));

    return convertView;
}

我想我应该在某处为 ImageView 清空,但我无法让它正常工作。ImageLoader 是一个(非常)简单的用于加载图像的类 - 从 LruCache、磁盘/sdcard 或远程获取它。

4

2 回答 2

15

您收到此错误是因为您无法访问回收的位图。正如 Android 开发者网站所说:

释放与此位图关联的本机对象,并清除对像素数据的引用。这不会同步释放像素数据;如果没有其他引用,它只是允许它被垃圾收集。该位图被标记为“死”,这意味着如果调用 getPixels() 或 setPixels() 将引发异常,并且不会绘制任何内容。此操作无法反转,因此只有在您确定位图没有进一步用途时才应调用它。这是一个高级调用,通常不需要调用,因为当没有更多对该位图的引用时,正常的 GC 进程将释放此内存。

我建议您到目前为止不要回收位图,因为它仍然有用。因此,请查看您的代码何时调用该recycle()方法,然后将其删除。

当 Bitmap 不再需要使用时,我建议您使用这种方法来处理 Bitmap:

public void disposeBitmap(Bitmap bitmap) {
        bitmap.recycle();
        bitmap = null;
}

我希望这有帮助。

于 2012-09-02T20:47:55.080 回答
8

事实证明,这个错误是由在我的类中调用覆盖 LruCacheoldBitmap.recycle()的方法引起的。entryRemoved(..)由于位图可能仍附加到 ImageView 调用recycle()会造成麻烦。

如果我理解正确:LruCache 的缓存大小将在其构造函数中设置。当项目数超过此大小时,对象将有资格进行垃圾收集,这将在位图不再与 ImageView 关联时发生。

网络上的许多示例和教程建议recycle()应该调用 in entryRemoved(..),但据我所知这是错误的。

于 2012-09-18T11:38:04.453 回答