android - 为什么这个图像切换代码有内存泄漏?

标签 android memory-leaks imageview

我正在编写一个简单的 android 应用程序,它使用 ImageView 来显示图像。当点击一个按钮时,它会根据当前图像生成一个新的位图,并替换旧的位图。

我用的图片不大:220 x 213

但是在模拟器中,当我点击按钮第5次时,它会抛出一个错误:

 java.lang.OutOfMemoryError: bitmap size exceeds VM budget

我读过一些文章:

  1. java.lang.OutOfMemoryError: bitmap size exceeds VM budget - Android
  2. http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
  3. http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html

但还是没有解决我的问题。

我的代码是:

public class MyActivity extends Activity {
    private Bitmap image;
    private ImageView imageView;
    private Button button;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        this.button = (Button) findViewById(R.id.button);
        this.imageView = (ImageView) findViewById(R.id.image);


        this.image = BitmapFactory.decodeResource(getResources(), R.drawable.m0);
        this.imageView.setImageBitmap(image);

        this.button.setOnClickListener(new View.OnClickListener() {
            private int current = 0;

            @Override
            public void onClick(View view) {
                Bitmap toRemove = image;
                Matrix matrix = new Matrix();
                matrix.setRotate(30, 0.5f, 0.5f);
                image = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true);
                imageView.setImageBitmap(image);

                if (toRemove != null) {
                    toRemove.recycle();
                }
            }
        });
    }
}

您可以看到我在删除图像上调用了 toRemove.recycle()。不过好像没什么效果。


更新:

由于错误只发生在我第 5 次点击按钮时(不是第一次),我们可以看到图像大小没有问题。在我的代码中,我试图在生成新图像后释放旧图像,所以我认为旧图像没有正确释放。

我已经调用了toRemove.recycle(),这是释放图像的正确方法吗?还是我要用别的东西?


最后:

Emile 是对的。我添加了一些代码来记录大小,您可以看到它每次都在增加:

08-28 13:49:21.162: INFO/image size before(2238): 330 x 320
08-28 13:49:21.232: INFO/image size after(2238): 446 x 442
08-28 13:49:31.732: INFO/image size before(2238): 446 x 442
08-28 13:49:31.832: INFO/image size after(2238): 607 x 606
08-28 13:49:34.622: INFO/image size before(2238): 607 x 606
08-28 13:49:34.772: INFO/image size after(2238): 829 x 828
08-28 13:49:37.153: INFO/image size before(2238): 829 x 828
08-28 13:49:37.393: INFO/image size after(2238): 1132 x 1132

最佳答案

我不太确定 Bitmap.createBitmap() 是如何工作的,但考虑到错误与“位图大小”有关

java.lang.OutOfMemoryError: bitmap size exceeds VM budget

我假设图像的大小会随着每次点击而增加。因此,错误发生在第 5 次点击时。

我建议大小增加与旋转矩阵有关。旋转图像时,它似乎并没有将旋转后的图像裁剪为图像的宽度和高度,而是增加了图像的大小。

您将不得不尝试一些替代方法来在您想要的 w/h 范围内操纵旋转。

这个问题的答案(向下两个)显示了如果您愿意,如何裁剪旋转的图像。 Android: How to rotate a bitmap on a center point

RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);

关于android - 为什么这个图像切换代码有内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12159852/

相关文章:

c++ - 从指针 vector 中删除元素

android - 从 BroadcastReceiver 更新适配器

android - 如何通过处理程序从 IntentService 多次调用 WebView Activity ?

java - 导入 com.google.android.gms.* 时出错;

c++ - 分配包含 STL vector 的结构时发生内存泄漏

CS50 PSET4 无法释放拼写器中的内存

android - 如何在Android中修复InvocationTargetException,OutOfMemoryError和IllegalStateException?

android - 在相机预览中将 ImageView 定位为叠加图像

android - setImageBitmap 不显示

Android - 在自定义 map 上绘制 gps 坐标