Android. 内存溢出问题

3

我需要在我的应用程序中显示许多图片,这些图片是jpg和png格式的,我会像这样把它们加载到ImageView中:

tile.setImageResource(R.drawable.tile_highlight);

我目前遇到了OutOfMemory问题 (java.lang.OutOfMemoryError: bitmap size exceeds VM budget)

我已经搜索并找到一些其他的文章,它们都建议你应该手动回收ImageView的位图,像这样:((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle(); 这将把它从内存中卸载。

但在我的情况下,因为我没有使用 setBitmap() 来加载图像到ImageView对象上,当我尝试运行上面的代码时,它返回NullPointerException,更确切地说,方法getBitmap()返回null,没有位图!?!

我需要回到我的代码并改变加载所有图像到ImageViews的方式,然后再尝试使用recycle()方法吗?或者我如何释放内存,使其不再崩溃?

编辑

我尝试了这样的代码:imageView.setImageResource(-1); 希望它会从内存中删除图像并用... null或其他替换它,但似乎它并没有帮助解决问题。


你可以在代码中加一个catch语句来捕获OutOfMemoryError,在catch里面你可以重新调整大小并再次设置到imageview上。 - rajpara
看这里:http://developer.android.com/reference/android/widget/ImageView.html#setImageResource(int) 考虑使用setImageDrawable并查看是否有帮助。Drawable image = context.getResources().getDrawable(R.drawable.image); ImageView.setImageDrawable(image); - Maxim
2
可能是 Out of Memory Error ImageView issue 的重复问题。 - rds
5个回答

4

如果您能发布一些代码,那将非常有帮助。具体来说,您是如何设置ImageView对象的图像的。如果您没有使用位图,则我预计getBitmap()将返回null。但是,如果您使用另一种类型的Drawable或其他方式来设置图像,则可能存在类似的路线,而不涉及位图。

编辑:

好的,请尝试这个。您可以从资源中创建一个Bitmap,如下所示:

Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);

然后,按照以下方式使用位图,假设img是您的ImageView:
img.setImageBitmap(bm);
//Do some stuff with it, then when memory gets low:
((BitmapDrawable)img.getDrawable()).getBitmap().recycle();

当然,这是考虑到您正在一个活动中。如果不是,您将需要掌握上下文,并将getResources()替换为context.getResources()


我只是使用setImageResource(R.drawable.someImage)来加载ImageViews内部的图像。 - AndreiBogdan
以上的代码无法解决这个问题。如果您的应用程序存在一些内存泄漏,就会遇到这个问题。位图回收可以帮助您,但这只是一个盲目的解决方案。在正常情况下,您不应该使用Bitmap.recycle()本地方法。尝试使用DDMS和来自Android SDK工具的hprof-conv分析您的HPROF。 - ddmytrenko

2

如果你想将一张图片从drawable设置到ImageView上,请不要直接使用ImageView.setImageResource(int resId)和drawable id。相反,获取缩小比例的位图(如果适用),并将其设置为imageView。像这样: 这对我有效。

    iv.setImageBitmap(decodeResource(getResources(), R.drawable.big_image));

    private static Bitmap decodeResource(Resources res, int id) {
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        for (options.inSampleSize = 1; options.inSampleSize <= 32; options.inSampleSize++) {
            try {
                bitmap = BitmapFactory.decodeResource(res, id, options);
                Log.d(TAG_LOG, "Decoded successfully for sampleSize " + options.inSampleSize);
                break;
            } catch (OutOfMemoryError outOfMemoryError) {
                // If an OutOfMemoryError occurred, we continue with for loop and next inSampleSize value
                Log.e(TAG_LOG, "outOfMemoryError while reading file for sampleSize " + options.inSampleSize
        + " retrying with higher value");
            }
        }
        return bitmap;
    }

来源: https://codingjunkiesforum.wordpress.com/2014/06/12/outofmemory-due-to-large-bitmap-handling-in-android/

在Android开发中处理大型位图可能会导致OutOfMemory异常。这是因为应用程序的内存限制和设备的内存限制。以下是一些优化技巧,以避免这种情况的发生:

  • 使用像Picasso、Glide等第三方库来加载图片。
  • 调整位图大小以减少内存占用。
  • 使用inSampleSize选项缩小位图。
  • 使用RGB_565格式而不是ARGB_8888格式。
  • 尽可能使用小的位图。
  • 及时回收不再需要的位图。

1

我认为你应该使用低分辨率的图片来展示。这可以解决OOM问题。你也可以阅读Android开发者指南link


1
当您不释放位图(可能是大尺寸)一旦使用后,就会出现OutOfMemory错误,因此为了防止这种情况发生,我们应该考虑重新调整大小、采用弱引用等方法。但是有一些很好的库可以解决所有问题,其中之一是Picasso,请查看以下链接:

使用Picasso加载图像


1

尝试

((BitmapDrawable)im.getBackground()).getBitmap().recycle();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接