【问题标题】:"Cannot draw recycled bitmaps" when displaying bitmaps in Gallery attached to Adapter在附加到适配器的图库中显示位图时“无法绘制回收的位图”
【发布时间】:2012-08-31 16:07:04
【问题描述】:

在 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 或远程获取。

【问题讨论】:

  • 能否请您显示 imageLoader 的代码 - 基本上,您的代码中似乎有一些位图的回收,然后您尝试显示位图(根据错误消息),但没有代码很难说。

标签: android


【解决方案1】:

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

释放与此位图关联的本机对象,并清除 参考像素数据。这不会释放像素数据 同步;它只是允许它被垃圾收集,如果有 没有其他参考。该位图被标记为“死”,这意味着它 如果调用 getPixels() 或 setPixels() 将抛出异常,并且 什么都不会画。此操作不可逆转,因此应 只有在您确定没有其他用途的情况下才会调用 位图。这是一个高级调用,通常不需要调用, 因为正常的 GC 进程会在没有 对此位图的更多引用。

我建议你不要回收 Bitmap,因为它还有用处。所以去看看你的代码什么时候调用recycle()方法然后删除它。

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

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

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 是的,假设您可以从entryRemoved() 调用recycle() 是不安全的。
    • 那么在使用 LruCache 时,你什么时候在代码中调用 recycle()?
    猜你喜欢
    • 2015-02-09
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    相关资源
    最近更新 更多