更改ImageView内容会导致OutOfMemoryError

时间:2010-02-03 11:11:05

标签: android android-widget

我有一个非常简单的应用程序,只有一个ImageView和一个Button。我的 ImageView 加载的第一个Drawable资源在XML Layout中使用“android:src”标记指定,但在运行时我想更改它显示的图片。为此,我启动一个活动结果从SD卡中选择一个图像(意图发送到MediaStore.Images.Media.EXTERNAL_CONTENT_URI)。但是,当选择图片时,我尝试使用所选图片的URI更新ImageView,但我收到消息“ java.lang.OutOfMemoryError:位图大小超过VM预算

我正在尝试加载我的HTC-Hero相机拍摄的照片(图片大小约为1.1M),但没有成功,似乎仅适用于小于500KB的照片。但是我需要加载拍摄的照片用相机。 我该如何解决这个问题?我做错了什么。在我看来代码很简单,应该可以工作。

public void onClick(View v){
 Intent selectImageIntent=new Intent(Intent.ACTION_PICK , 
   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
   startActivityForResult(selectImageIntent,1);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
 super.onActivityResult(requestCode, resultCode, data);
 if(resultCode==Activity.RESULT_OK){
   Uri selectedImageUri = data.getData();
   Log.i(TAG,"chosen image: "+selectedImageUri.toString());
   ImageView imageView = (ImageView) this.findViewById(R.id.ImageView01);
   imageView.setImageURI(selectedImageUri);//here I get the OutOfMemoryError
   imageView.invalidate();

 }else{
  //canceled
 }

}

P.S。这是应用程序应该做的唯一事情,我不是在创建其他对象,所以我想指出除了显示图像之外我不会将堆空间用于其他东西。

5 个答案:

答案 0 :(得分:43)

似乎在加载新的Bitmap之前我必须回收ImageView显示的Bitmap,现在它正在运行而没有问题。希望这有助于其他人,只需在设置新的ImageView内容之前调用下面的方法。

<强> ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();

所以代码现在看起来像这样:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode){
        case INTENT_REQUEST_SELECT_IMAGE:
            if(resultCode==Activity.RESULT_OK){
                Uri selectedImageUri = data.getData();
                Log.i(TAG,"selectedImageUri.getPath()"+selectedImageUri.getPath() );
                ImageView imageView = (ImageView) this.findViewById(R.id.ImageView_of_text);
                ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
                imageView.setImageURI(selectedImageUri);
                imageView.invalidate();

            }else{
                //TODO define what to do in case the user canceled OCR or any other event
            }
            break;
        default:
            break;
    }
}

请注意在ImageView的位图上调用回收。

答案 1 :(得分:6)

这让我疯了。

我正在建造一个拥有非常大的高分辨率全屏图像(800x1232)的Xoom。

以下代码对我有用:

public void onStop()
{
    super.onStop();
    imageView.setImageBitmap(null);
}
祝你好运!!!

答案 2 :(得分:2)

问题现在已经解决了。 而不是只有一行:

((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); 

在更新ImageView内容之前添加此代码:

Drawable toRecycle= gallerypic.getDrawable();
if (toRecycle != null) {
    ((BitmapDrawable)gallerypic.getDrawable()).getBitmap().recycle();
}
gallerypic.setImageURI(selectedimage);

答案 3 :(得分:1)

仅在更新imageview之前使用此功能:     imageView1.setImageURI(NULL);

答案 4 :(得分:1)

我使用了这篇文章的所有解决方案以及更多但没有人工作。最后我使用了android:largeHeap="true" 在清单中,这解决了我的问题。

希望这有助于某人。