回收 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】:
如果您在所有ImageView
s 上设置相同的位图对象,则不应抛出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的主要内容,如果未能解决你的问题,请参考以下文章