更改 ImageView 内容会导致 OutOfMemoryError

Posted

技术标签:

【中文标题】更改 ImageView 内容会导致 OutOfMemoryError【英文标题】:Changing ImageView content causes OutOfMemoryError 【发布时间】:2011-01-12 13:56:24 【问题描述】:

我有一个非常简单的应用程序,只有一个 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
 


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

【问题讨论】:

【参考方案1】:

似乎在加载新位图之前我必须回收 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的Bitmap上的recycle调用。

【讨论】:

【参考方案2】:

这让我发疯了。

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

以下代码对我有用:

public void onStop()

    super.onStop();
    imageView.setImageBitmap(null);

祝你好运!!!

【讨论】:

如果您将 FragmentStatePagerAdapter 与 ImageViews 一起使用,此方法将节省您的时间,因为在重新膨胀视图时回收位图会导致错误。【参考方案3】:

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

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

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

Drawable toRecycle= gallerypic.getDrawable();
if (toRecycle != null) 
    ((BitmapDrawable)gallerypic.getDrawable()).getBitmap().recycle();

gallerypic.setImageURI(selectedimage);

【讨论】:

【参考方案4】:

只在更新 imageview 之前使用这个: imageView1.setImageURI(null);

【讨论】:

【参考方案5】:

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

希望这对某人有所帮助。

【讨论】:

以上是关于更改 ImageView 内容会导致 OutOfMemoryError的主要内容,如果未能解决你的问题,请参考以下文章

像这样更改字符串的内容是不是会导致异常?

为啥表格视图单元格中的自动布局会导致表格的内容大小被错误地更改?

更改 ImageView 的背景很慢

Android imageview更改色调以模拟按钮单击

根据 CollectionView 中的选择更改 ImageView

无法在 RemoteView Android 上更改 ImageView 资源