回收 ImageView 的 Bitmap

Posted

技术标签:

【中文标题】回收 ImageView 的 Bitmap【英文标题】:Recycle ImageView's Bitmap 【发布时间】:2011-10-23 22:59:06 【问题描述】:

我有这样的事情:

Bitmap.Config conf = Bitmap.Config.ARGB_8888;
WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, conf));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView.setImageBitmap(bm);

我将它应用到 10 多个图像视图上,这些图像视图是一一创建的。 每当我创建新的 ImageView 时,我想从第一个对象中回收 'bm' 对象,导致这段代码在那里,导致我的堆越来越大,然后抛出 OutOfMemoryError,所以我这样做:

bm.recycle()

在我将位图 (bm) 设置为 imageView 对象之后。 这会导致 ImageView 的画布要绘制回收的 Bitmap 的异常。

如何回收已经作为图像放在ImageView上的Bitmap?

谢谢b

【问题讨论】:

就在imageView.setImageBitmap(bm);之后并在此块结束..没有其他行。 【参考方案1】:

在你的 onDestroy 方法中,你可以尝试这样的事情:

ImageView imageView = (ImageView)findViewById(R.id.my_image);
Drawable drawable = imageView.getDrawable();
if (drawable instanceof BitmapDrawable) 
    BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    Bitmap bitmap = bitmapDrawable.getBitmap();
    bitmap.recycle();

由于 setImageBitmap 实现为

public void setImageBitmap(Bitmap bm) 
    setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));

【讨论】:

在他的情况下,也许应该在他再次致电setImageBitmap()之前完成。 我无权访问使用 ImageView 的 Activity,我只是实现了自定义 ImageView,所以我认为 ImageView 类本身具有某种机制作为 C++ 中的析构函数或任何信号知道不再使用该 ImageView 的非常实例.. 我必须对所有图像执行此操作还是仅对大图像执行此操作。我不能将另一个图像分配给图像视图吗?【参考方案2】:

如果您在所有ImageViews 上设置相同的位图对象,则不应抛出OutOfMemoryError。基本上,这应该有效:

WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, Bitmap.Config.ARGB_8888));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView1.setImageBitmap(bm.get());
imageView2.setImageBitmap(bm.get());
imageView3.setImageBitmap(bm.get());
imageView4.setImageBitmap(bm.get());
imageView5.setImageBitmap(bm.get());
// ...

如果这不起作用,则仅表示您的位图太大(如果我计算正确,6000x2000 像素约为 12 兆字节)。您可以:

使您的位图更小 减少使用大量内存的其他内容

【讨论】:

问题是,即使我回收使用 .createBitmap 创建的位图,每次此方法结束时堆都会增长。我在检查它是否正常后立即回收它 - 不,堆增长了。所以我想这是泄漏.. 12Mpx != 12MB。它可能会占用比 12MB 更多的内存。一个 12Mpx 的位图可能需要超过 35MB。【参考方案3】:

任何时候都不要创建比您需要的更大的图像。堆限制旨在防止您上吊并完全接管设备的有限内存。

如果您因为计划放大而需要更多细节,则在缩放时重新渲染具有更高细节的图像部分,不包括您未查看的部分。

【讨论】:

【参考方案4】:

Devconsole 的回答很好,但是您也可以像类成员一样将所有位图对象存储在列表中,然后在活动的 onDestroy() 方法(或您使用的组件的其他发布生命周期方法)中循环回收它们位图)将被调用。

【讨论】:

以上是关于回收 ImageView 的 Bitmap的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQLite、imageView 和可回收的 RecyclerView 性能 = false

具有全屏缩放的 ImageView

在 ImageView 中放置许多 TextView

Android 实现瀑布流的两种思路

ImageView 上的渐变层重用

将图像从 imageview 上传到 Firebase Android