首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有大尺寸高分辨率图像的java.lang.OutOfMemory

具有大尺寸高分辨率图像的java.lang.OutOfMemory
EN

Stack Overflow用户
提问于 2013-01-10 00:55:22
回答 3查看 1K关注 0票数 1

我正在开发一个Android应用程序,它在几个活动中使用多个大图像。每个图像大约是1280x800,我为每个活动加载了大约2-4个这样的图像。我意识到这些图像在分配给设备上每个应用程序的内存方面非常大,但我如何才能在不遇到java.lang.OutOfMemory错误的情况下以原始分辨率显示它们?我需要这些图像以它们的完整尺寸显示在屏幕上(当屏幕比图像小时,缩放由xml自动完成)。我看到了几种解决方案,包括将图像缩小为缩略图并将其存储到内存中,但这不会导致图像失去其原始大小/分辨率吗?谢谢你的帮忙!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-10 01:16:14

This article很好地描述了如何创建堆转储并使用Eclipse MAT对其进行分析。这将帮助您快速找到内存泄漏的最有可能的嫌犯。

我再一次向你指出this great link,我从另一个问题中找到了如何正确解决这个问题的教程。

票数 1
EN

Stack Overflow用户

发布于 2013-01-10 01:04:52

对此您可以做几件事。

首先想到的是1280x800 (可能)是您的整个屏幕,所以您应该一次只显示一个屏幕。当你这样做的时候,不要把其他的东西留在内存中。

每像素4字节的1280x800图像仍然只有4MB,而且现在平板电脑似乎都提供了48MB的堆。如果需要,您应该能够在内存中保留一些。如果内存不足,则可能是内存泄漏。如果您在DDMS中观察,您的内存使用量是否会随着您更改活动而继续增长?

泄漏的一个常见来源是位图本身。当你用完它们时,一定要调用Bitmap#recycle

如果确实如此,并且您无法适应所提供的堆空间,那么您还可以尝试将android:largeHeap="true"添加到清单中的应用程序标记中。这将要求系统为您提供更多的堆空间-在某些设备上高达256MB。不过,这应该是最后的手段,因为它会因设备而异,在一些设备上完全被忽略(脑海中浮现出最初的Kindle Fire )。

您可以使用Runtime.getRuntime().maxMemory();查看您拥有的总堆空间大小。有关详细说明,请参阅this answer。要知道你到底使用了多少比较棘手,但如果你想解决这个问题,有一个here描述。

最后,可能有一种比在xml中指定图像更好的加载图像的方法。请务必阅读此developer guide page。即使您必须将它们保留在xml中,但通过将图像资产拆分到drawable-hdpidrawable-mdpi等目录中,而不只是将它们转储到drawable中,我已经看到了内存使用的显著改进。

票数 3
EN

Stack Overflow用户

发布于 2013-01-10 04:21:34

在使用BitmapFactory或相关方法加载图像之前,需要对图像进行缩放。

代码语言:javascript
复制
public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

整个事情都在Android开发者网站Loading Large Bitmaps Efficiently中进行了解释。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14242318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档