加载大背景图像时的OutOfMemory

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (52)

android:background用来给android布局提供背景图片。 放一些图像后,我得到了这个例外:

08-24 00:40:19.237: E/dalvikvm-heap(8533): Out of memory on a 36000016-byte allocation.

如何在android上使用大图像作为背景? 我可以扩展应用程序堆内存吗?还是不好的事情?

提问于
用户回答回答于

请看一下我的相关问题:

高分辨率图像 - OutOfMemoryError

尝试通过保持背景图像尽可能小来最小化应用程序的内存使用量。

这可以通过以下方式完成:

  • 裁剪图像以使其适合屏幕
  • 甚至在应用程序中使用它之前进一步压缩图像(例如使用photoshop)
  • 使用以下方法加载您的位图
  • 一旦你没有需要它就回收位图
  • 确保你没有在内存中保留多个实例
  • 使用位图后,将引用设置为null

确保您设置为背景的图像正确加载(例如裁剪尺寸,例如适合屏幕尺寸),并在不再需要时立即从内存中释放。

确保内存中只有一个Bitmap实例。显示后,调用recycle()并将引用设置为null。

这是你加载图像的方法:

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);
}

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) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

感谢Adam Stelmaszczyk为这段美丽的代码。

用户回答回答于

由于布局中的背景图像,我遇到了类似的问题。图像的内存分配的正常大小应为height * width * 4字节(在模式ARGB_8888中,默认模式)。

如果您在显示活动时看到并分配30MB,则必定存在一些问题。检查是否将背景图像放在drawable文件夹中。在这种情况下,系统必须将该图像缩放到屏幕的特定密度,从而导致大量内存开销。

解决方案:

  1. 在每个可绘制文件夹中放置特定版本的背景图像(mdpi,hdpi,xhdpi ...)。
  2. 将背景图像放在名为“drawable-nodpi”的特殊资源文件夹中。系统不会尝试缩放放在此目录中的图像,因此只执行拉伸过程并分配的内存将是预期的。

答案中的更多信息

希望这可以帮助。

扫码关注云+社区

领取腾讯云代金券