android - 创建位图时的内存不足异常

dro*_*ter 14 android memory-leaks bitmap

在第二次创建位图后,我收到以下错误:

04-17 18:28:09.310: ERROR/AndroidRuntime(3458): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

this._profileBitmap = Bitmap.createBitmap(_profileBitmap, xCoor,  yCoor, width, height);
Run Code Online (Sandbox Code Playgroud)

从日志:

04-17 18:27:57.500: INFO/CameraCropView(3458): Original Photo Size: W 1536 x H 2048   
04-17 18:28:06.170: INFO/CameraCropView(3458): xCoor: 291   
04-17 18:28:06.170: INFO/CameraCropView(3458): yCoor: 430    
04-17 18:28:06.170: INFO/CameraCropView(3458): Width: 952  
04-17 18:28:06.170: INFO/CameraCropView(3458): Height: 952  
Run Code Online (Sandbox Code Playgroud)

由于图像很大,我得到了错误.但有趣的是错误不是第一次发生,只有当我第二次拍摄时才会发生,这让我相信这个profileBitmap不会被破坏.我该如何清理它?

小智 16

我有同样的问题并以这种方式解决它:

我的应用程序重量约为18MB,当我看到剩余多少内存时,我感到震惊 - 654KB(1GB内存!).所以我刚从项目中删除了几乎所有图像,并在第一次启动时从互联网上下载,并在需要时使用SD卡中的图片.

要检查应用的总/可用内存,请使用:

 Runtime.getRuntime().totalMemory();
 Runtime.getRuntime().freeMemory();
Run Code Online (Sandbox Code Playgroud)

编辑:我忘记了主要的事情 - 在活动标签之间添加你的清单,这一行:

机器人:largeHeap = "真"

  • 如果您很少出现内存错误,则可以正常工作.android:largeHeap ="true"不会使你的图像加载效率更高,但会带来更多内存. (2认同)
  • 使用大堆只是推迟了问题,如果可能的话,首选方法是重新考虑解码过程,删除未使用的资源等。 (2认同)

Tho*_*asW 12

在Android上使用位图的内存异常存在许多问题,其中许多都在stackoverflow上讨论过.如果你经历了现有的问题,看看你的问题是否与现有问题相匹配,那么最好是最好的,如果没有,请写出使你的情况不同的原因.

一些例子:

由于位图大小较大而导致内存不足

Android:Gallery中的内存不足异常

Android在图像处理上处理内存不足异常

等:https: //stackoverflow.com/search?q = android+out +of+memory+exception+bitmap


Dev*_*ine 7

android位图处理技巧

现在,这里有一些提示,您可以遵循这些提示,并避免Android应用程序中的内存不足异常.

  1. 始终使用Activity上下文而不是Application上下文.因为Application上下文不能被垃圾收集.并在活动结束时释放资源.(对象的生命周期应与活动相同).

2.活动结束时.检查HEAP DUMP(Android studio中的内存分析工具).

如果HEAP DUMP中的对象来自完成的活动,则存在内存泄漏.检查您的代码并确定导致内存泄漏的原因.

  1. 始终使用inSampleSize

现在什么是inSampleSize?在inSampleSize的帮助下,你实际上是在告诉解码器不要抓住内存中的每个像素,而是取样子图像.这将导致在内存中加载的像素数量少于原始图像.您可以告诉解码器从原始图像中抓取每第4个像素或每秒像素.如果inSampleSize为4.解码器将返回一个Image,它是原始图像中像素数的1/16.

你节省了多少记忆?计算 :)

  1. 在加载到内存之前读取位图尺寸.

    如何在将图像加载到内存之前读取位图尺寸可以帮助您避免
    内存不足错误?让我们来学习

    使用inJustBounds = true

这里的技术可以帮助您将图像尺寸加载到内存中

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage,    options);
 int imageHeight = options.outHeight;
 int imageWidth = options.outWidth;
 String imageType = options.outMimeType;
Run Code Online (Sandbox Code Playgroud)

上面的代码片段不会给我们任何图像/位图.它将为位图Object返回null.但它肯定会返回该图像的宽度和高度.这是R.id.myimage.

现在你有了Image的宽度和高度.您可以根据以下因素放大或缩小图像:

  • ImageView大小将用于显示图像.
  • 可用的内存量.您可以使用ActivityManager和getMemoryClass检查可用的内存量.
  • 屏幕尺寸和设备密度.

    1. 使用适当的位图配置

    位图配置是图像的颜色空间/颜色深度.Android中的默认位图配置是RGB_8888,每像素4个字节.

如果您使用RGB_565颜色通道,每个像素使用2个字节.相同分辨率的内存分配的一半:)

  1. 使用inBitmap属性进行回收.

  2. 不要制作静态Drawable Object,因为它不能被垃圾收集.

  3. 在清单文件中请求大堆.

  4. 如果您正在进行大量图像处理(内存密集型任务)或使用NDK(使用c,c ++进行本机开发),请使用多个进程

  • 请不要在多个问题上添加相同的答案.回答最好的一个并将其余部分标记为重复.请参阅[在几个问题中添加重复答案是否可以接受?](http://meta.stackexchange.com/q/104227) (2认同)

sko*_*lis 5

使用完位图后,您可以尝试调用 recycle() 。这将清除所有图像数据并释放内存。如果此后有任何东西尝试绘制位图,那么您的应用程序将崩溃。如果您确实发生了崩溃,它可能会帮助您找出位图上仍然保留着什么。


and*_*oid 5

发生这种情况是因为您直接加载位图,这会占用大量内存。而是在_profileBitmap中使用图片的缩小版本。这个家伙解释得很好。 http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html