20

我有一个非常简单的应用程序,其中包含一个 ImageView 和一个 Button。我的ImageView加载的第一个 Drawable 资源是用 XML 布局中的“android:src”标签指定的,但是在运行时我想更改它显示的图片。为此,我启动了一个 Activity 以从 sd 卡中选择图像(意图发送到 MediaStore.Images.Media.EXTERNAL_CONTENT_URI)。However when the picture is selected, i try to update the ImageView with the chosen Picture's URI but i get the message " java.lang.OutOfMemoryError: bitmap size exceeds VM budget "

我正在尝试加载用我的 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
 }

}

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

4

5 回答 5

43

好像在加载新位图之前我必须回收 ImageView 显示的位图,现在它可以正常工作了。希望这对其他人有帮助,只需在设置新 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 的位图上的回收调用。

于 2010-02-04T14:44:11.753 回答
6

这让我发疯了。

我正在为具有非常大的高分辨率全屏图像 (800x1232) 的 Xoom 构建。

以下代码对我有用:

public void onStop()
{
    super.onStop();
    imageView.setImageBitmap(null);
}

祝你好运!!!

于 2011-03-12T00:55:06.073 回答
2

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

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

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

Drawable toRecycle= gallerypic.getDrawable();
if (toRecycle != null) {
    ((BitmapDrawable)gallerypic.getDrawable()).getBitmap().recycle();
}
gallerypic.setImageURI(selectedimage);
于 2010-10-15T01:01:02.447 回答
1

仅在更新 imageview 之前使用它: imageView1.setImageURI(null);

于 2013-12-20T12:08:26.830 回答
1

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

希望这可以帮助某人。

于 2015-04-08T11:56:14.567 回答