Android 位图处理 - 没有泄漏但仍然 OOM?

Android bitmap processing - no leak but still OOM?

我正在编写一个相机应用程序,当我拍照时,我收到一个字节 [],将其解码为位图并在将其保存为 JPEG 之前对其进行旋转。我正在使用本机库旋转照片,但是位图仍然从 byte[] 解码到内存中(仍然允许我保留 1 个位图而不是 2 个)。所以基本上在我的代码中有 1 个地方我需要大量内存和 OOM 在一些堆低且相机是愚蠢的百万像素的设备上。对如何在不降低图像质量的情况下解决此问题有何建议?

我不想用 largeHeap="true" 我应该忘记旋转而只设置 EXIF 吗?

另外,我不太热衷于尝试 'predict' 如果我会 OOM,因为数学没有加起来:Android OutOfMemory when GC reports free memory?

Any suggestions how to fix this without on loosing image quality?

使用android:largeHeap="true".

或者,使用其他一些允许您移交 byte[] 并为您旋转并保存到磁盘的本机库,以避免 Bitmap 和任何 Java-level巨大的东西的处理。

或者,如果您的 minSdkVersion 是 19,并且您的其他逻辑支持它,请在 BitmapFactory.Options 上使用 inBitmap 尝试重用 already-allocated Bitmap object 而不是分配一个新的。此选项在 Android 的早期版本中可用,但对于那些它必须在分辨率方面完全匹配;在 19 岁以上,要重复使用的 Bitmap 必须足够大以处理您要加载到其中的内容。

I don't think I want to use largeHeap="true"

这可能无济于事(并非所有设备都会为您提供更大的堆),并且用户需要为更大的堆限制付出代价。话虽这么说,如果没有更多内存,操作大型相机图像是很困难的,无论是在 Java 堆中还是代表来自本机代码的 OS 的分配。

Should I forget about rotation and just set EXIF?

这当然是另一种可能性,尽管 ImageView 等各种东西似乎忽略了 EXIF headers。

I'm not so keen on trying to 'predict' if I will OOM as the math's not adding up

部分原因是 Dalvik 没有 compacting/moving GC,而当您的应用程序不在前台时,ART 只有一个。 OutOfMemoryError 表示您尝试分配的内容没有单个连续的空闲内存块。

您可能没有足够的内存来创建大位图的旋转副本。

您可以改为绘制原始图像的旋转图像。


另外在处理图片的时候还有一些需要注意的地方:

  • 始终加载缩放到 ImageView 大小的图像。
  • 始终回收您的图片
  • 如果仍有问题,请考虑使用 largeHeap=true。 Android 堆大小的增长可能太慢(参见 )。