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

时间:2011-04-18 01:44:00

标签: 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);

来自日志:

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  

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

9 个答案:

答案 0 :(得分:14)

我遇到了同样的问题并以这种方式修复:

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

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

 Runtime.getRuntime().totalMemory();
 Runtime.getRuntime().freeMemory();
编辑:我忘了主要的事情 - 在活动标签之间添加你的清单,这一行:

<强>机器人:largeHeap = “真”

答案 1 :(得分:13)

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

一些例子:

Out of memory exception due to large bitmap size

Android: out of memory exception in Gallery

Android handling out of memory exception on image processing

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

答案 2 :(得分:6)

android bitmap processing tips

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

  1. 始终使用Activity上下文而不是Application上下文。因为Application上下文不能被垃圾收集。并在活动结束时释放资源。 (对象的生命周期应该是 与活动相同)。
  2. 2。活动结束时。检查HEAP DUMP(Android studio中的内存分析工具)。

    如果HEAP DUMP中的对象来自完成的活动,则存在内存泄漏。检查你的 代码并识别导致内存泄漏的原因。

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

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

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

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

        使用inJustBounds = true

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

         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;
        

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

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

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

          1. 使用适当的位图配置
          2. 位图配置是图像的颜色空间/颜色深度。 Android中的默认位图配置为RGB_8888,即每像素4个字节。

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

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

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

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

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

答案 3 :(得分:4)

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

答案 4 :(得分:2)

完成后,您可以尝试在位图上调用recycle()。这将清除所有图像数据并释放内存。如果有任何事情在此之后尝试绘制位图,那么您的应用程序将崩溃。如果你遇到崩溃,它可能会帮助你找出仍然保留在你的位图上的内容。

答案 5 :(得分:2)

您可以使用Vector Drawable。它使用xml文件来描述您的图像,因此它消耗的内存较少。 为此,您应该为图像使用SVG格式,然后使用以下两种解决方案之一生成xml文件:

  • 解决方案1:在Android Studio中使用vector asset studio:右键单击项目中的Drawable文件 - &gt;新的 - &gt;矢量资产
  • 解决方案2:使用svg2android网站:https://inloop.github.io/svg2android

查看此链接以获取更多信息:
https://developer.android.com/studio/write/vector-asset-studio.html

答案 6 :(得分:1)

对于较大的图像,可以通过将它们采样为较小的尺寸来避免。 使用以下示例 -

    File f = new File(selectedImagePath); 

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, options); 
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, 720, 1280); //My device pixel resolution
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;    
    Bitmap bmpPic = BitmapFactory.decodeStream(new FileInputStream(f), null, options); 


    Bitmap bmpPic1 = Bitmap.createBitmap(bmpPic, 0, 0, bmpPic.getWidth(), bmpPic.getHeight(), mat, true);   
    img.setImageBitmap(bmpPic1);  //img is your ImageView

参考 - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

答案 7 :(得分:1)

我遇到了这个问题,因为我一次修改了一个位图,然后第二次修改了修改后的版本,导致同一位图的三个版本(原始版本,再加上两个修改版本)同时存储在内存中。

我通过更改图像编辑代码以将这两种修改以一种批处理的方式应用于同一位图的方式将其修改,从而将我的应用程序必须保留在内存中的修改版本减少了一半。

答案 8 :(得分:0)

手机关闭电源后又出现了同样的问题。只需将位图设置为null并调用System.gc();解决了所有问题。