2012-08-28 165 views
1

我正在写一个简单的android应用程序,它使用ImageView来显示图像。当点击一个按钮时,它会根据当前图像生成一个新的位图,并替换旧的位图。为什么这个图像切换代码有内存泄漏?

我用的图片并不大:220 x 213

但在模拟器中,当我点击按钮的时候,它会抛出一个错误:

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


UPDATE:

由于错误只发生时我按一下按钮第五次(不是第一次),我们可以看到的图像尺寸是没有问题的。在我的代码中,我试图在生成新图像后发布旧图像,所以我认为旧图像尚未正式发布。

我已经调用toRemove.recycle(),这是释放图像的正确方法吗?或者我会使用别的东西?


FINALLY:

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

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

登录在你的onClick()方法的开始和结束的宽度和高度。查看图片是否随着每次点击而改变大小。 – Emile

+0

有可能你在其他地方有内存泄漏,位图恰好是用尽剩余内存的对象。 – mbeckish

+0

@Emile,谢谢!你是对的!我会将日志附加到问题 – Freewind

回答

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); 
+0

我跟着你提供的链接和代码,但仍然没有得到正确的结果。请帮助我解决这个问题:http://stackoverflow.com/questions/12163801/how-to-rotate-an-image-many-times-but-always-keep-the-4-corners-of-original-imag – Freewind