Android 解码大位图时发生OutOfMemoryError

Android 解码大位图时发生OutOfMemoryError,android,Android,我正在开发一个android应用程序,它可以解码jpeg文件,并使用canvas.drawBitmap()在画布上绘制位图。我正在使用BitmapFactory.decodeStream()将jpeg解码为位图 当我处理分辨率为2560x1536的图像时,一切正常。最近,我做了一个压力测试,试图打开一个真正大的分辨率为5400x3600的jpeg。我的应用程序崩溃,错误为“java.lang.OutOfMemoryError” 以下是堆栈跟踪: java.lang.OutOfMemoryErro

我正在开发一个android应用程序,它可以解码jpeg文件,并使用canvas.drawBitmap()在画布上绘制位图。我正在使用BitmapFactory.decodeStream()将jpeg解码为位图

当我处理分辨率为2560x1536的图像时,一切正常。最近,我做了一个压力测试,试图打开一个真正大的分辨率为5400x3600的jpeg。我的应用程序崩溃,错误为“java.lang.OutOfMemoryError”

以下是堆栈跟踪:

java.lang.OutOfMemoryError
    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
    at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:720)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:734)
    ...
这是可以理解的,因为这是一个大的图像和解码位图使用大量的内存

然而,我想了解的是,在同一部手机上,如果我使用gallery应用程序,gallery应用程序可以毫无问题地显示相同的大图像

在同一部手机上,如果我也尝试用一些图片编辑工具打开相同的大图像,我认为应该将jpeg解码成位图,那么一切都很好。这些应用程序显示图像需要更多的时间,但图像是在屏幕上加载和绘制的


我试图了解我可能做错了什么,并且与其他应用程序相比有所不同?

首先,您需要设置

 android:largeHeap="true"
在Android清单中。 然后它的错觉,同样大小的图像显示在系统画廊。 实际上,每个库或库都会根据屏幕上的可用大小调整图像大小,方法是保持图像的纵横比和质量

所以,在从系统中获取大图像之前,您需要调整图像大小

高效加载大型位图

读取位图尺寸和类型

BitmapFactory类提供了几种解码方法(decodeByteArray(),
decodeFile()
decodeResource()
,等等),用于从各种源创建位图。根据图像数据源选择最合适的解码方法。这些方法试图为构造的位图分配内存,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的签名,可以通过BitmapFactory.options类指定解码选项。解码时将
inJustDecodeBounds
属性设置为true可避免内存分配,为位图对象返回null,但设置
outWidth
outHeight
outMimeType
。此技术允许您在构建位图(和内存分配)之前读取图像数据的尺寸和类型

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
要避免java.lang.OutOfMemory异常,请在解码位图之前检查位图的尺寸,除非您完全信任源为您提供可预测大小的图像数据,这些数据可以轻松地放入可用内存中

将缩小的版本加载到内存中 既然图像尺寸已知,就可以使用它们来决定是应该将完整图像加载到内存中,还是应该加载子采样版本。以下是一些需要考虑的因素:

在内存中加载完整映像的估计内存使用量。 考虑到应用程序的任何其他内存需求,您愿意承诺加载此映像的内存量。 要加载图像的目标ImageView或UI组件的维度。 当前设备的屏幕大小和密度

Java虚拟机无法分配对象时引发,因为 内存不足,服务器无法提供更多内存 垃圾收集器

确保,补充道

<application
    android:largeHeap="true"
   >
此方法可以轻松地将任意大的位图加载到显示100x100像素缩略图的ImageView中,如下代码所示:

imgOBJ.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

您可以检查

您的答案在这里[LINK]{}您是否将这些图像存储在可绘图文件夹中?欢迎@RichardT
imgOBJ.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));