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

时间:2012-08-28 13:02:08

标签: android memory-leaks imageview

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

我使用的图像并不大: 220 x 213

但是在模拟器中,当我点击 5th 时间按钮时,会出现错误:

 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
  4. 但仍然没有解决我的问题。

    我的代码是:

    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()。但似乎没有效果。


    更新:

    由于仅在我第五次(不是第一次)点击按钮时发生错误,我们可以看到图像大小不是问题。在我的代码中,我尝试在生成新图像后释放旧图像,因此我认为旧图像尚未正确发布。

    我调用了toRemove.recycle(),这是发布图片的正确方法吗?或者我会用别的东西吗?


    最后:

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

    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
    

1 个答案:

答案 0 :(得分:2)

我不确定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);