【问题标题】:Out of Memory error with Bitmap位图内存不足错误
【发布时间】:2015-07-22 14:48:16
【问题描述】:

在运行时,我试图将图像放在表面视图中。当我尝试使用 Drawable 文件夹中的图像时,出现内存不足错误。在 stackoverflow 中快速搜索后,我发现如果我们从资产文件夹中访问图像会有所缓解。但是我仍然在运行时遇到内存不足错误。

我分析并发现缩放将有助于解决这种与内存相关的问题。问题是我的图像尺寸为 1280 x 720,设备尺寸也相同。因此,我觉得缩放不会有任何效果。

由于我们在这个社区中有专家,如果您能帮助我提供一些解决此类问题的建议/示例,我将不胜感激。

场景一:

使用 Drawable 文件夹中的位图。

backgoundImage = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.backgroundhomepage), (int) dWidth, (int) dHeight, true);

    /***********************************************************************************************************************************************************
    1.  To get the image from asset library
     **************************************************************************************************************************************************************/ 

    public  Bitmap getAssetImage(Context context, String filename) throws IOException {
        AssetManager assets = context.getResources().getAssets();
        InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
        Bitmap bitmap = BitmapFactory.decodeStream(buffer);
        return bitmap;
    }

场景 2:

使用 Assets 文件夹中的位图

backgoundImage = Bitmap.createScaledBitmap(getAssetImage(context,"backgroundhomepage"), (int) dWidth, (int) dHeight, true);

【问题讨论】:

标签: android android-canvas android-image


【解决方案1】:

当您的应用超出堆中分配的内存时,就会发生 OutofMemory。位图太大而无法放入内存(即堆)中。在这种情况下,您的内存不足。您需要按比例缩小位图,然后使用相同的。为此请检查下面的链接

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

还有一个博客@http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html(避免内存泄漏)

 public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
 try {
     //Decode image size
     BitmapFactory.Options o = new BitmapFactory.Options();
     o.inJustDecodeBounds = true;
     BitmapFactory.decodeStream(new FileInputStream(f),null,o);

     //The new size we want to scale to
     final int REQUIRED_WIDTH=WIDTH;
     final int REQUIRED_HIGHT=HIGHT;
     //Find the correct scale value. It should be the power of 2.
     int scale=1;
     while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
         scale*=2;

     //Decode with inSampleSize
     BitmapFactory.Options o2 = new BitmapFactory.Options();
     o2.inSampleSize=scale;
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
 } catch (FileNotFoundException e) {}
 return null;
}

引用文档

BitmapFactory 类提供了几种解码方法(decodeByteArray()、decodeFile()、decodeResource() 等),用于从各种来源创建位图。根据您的图像数据源选择最合适的解码方法。这些方法尝试为构造的位图分配内存,因此很容易导致 OutOfMemory 异常。每种类型的解码方法都有额外的签名,允许您通过 BitmapFactory.Options 类指定解码选项。

在解码时将 inJustDecodeBounds 属性设置为 true 可避免内存分配,为位图对象返回 null,但设置 outWidth、outHeight 和 outMimeType。此技术允许您在构建位图(和内存分配)之前读取图像数据的尺寸和类型。

还可以查看此链接以了解内存管理。

https://www.youtube.com/watch?v=_CruQY55HOk

【讨论】:

  • 位图尺寸 - 1280 x 720,尺寸仅为 127KB,设备尺寸与图像尺寸 1280 x 720 相同。我们为什么要缩放它?
  • 它太大了,您的应用程序将超过分配的堆大小。因此你需要缩小规模。每个设备都有自己的堆大小。每个应用程序都在堆中分配了一定的内存空间。如果超出分配的内存,您可能会遇到内存泄漏。屏幕尺寸和宽度是多少?
  • 你的意思是说 127 KB 是工具大?如果我按比例缩小,图像质量会发生显着变化吗?
  • 您的应用中还有其他图片吗?你的屏幕高度和宽度是多少。
  • @iappmaker 检查堆大小。检查链接developer.android.com/reference/android/app/…
【解决方案2】:

有一个快速的解决方案

<application
     android:largeHeap="true" >

放入清单文件中的应用程序标签。

【讨论】:

  • 这个有什么副作用吗?
  • 并非在所有情况下都建议使用 largeHeap,请谨慎使用,它可能会减慢其他正在运行的应用程序,并且还会影响您的应用程序的响应性,因为垃圾收集器会更频繁地被请求。有关更多信息,请查看来自 google i/o youtube.com/watch?v=_CruQY55HOk 的演讲
【解决方案3】:

您可以使用以下代码从文件中加载位图:

private Bitmap decodeFile(File f,int req_Height,int req_Width){
    try {
        //decode image size
        BitmapFactory.Options o1 = new BitmapFactory.Options();
        o1.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o1);


        //Find the correct scale value. It should be the power of 2.
        int width_tmp = o1.outWidth;
        int height_tmp = o1.outHeight;
        int scale = 1;

        if(width_tmp > req_Width || height_tmp > req_Height)
        {
             int heightRatio = Math.round((float) height_tmp / (float) req_Height);
             int widthRatio = Math.round((float) width_tmp / (float) req_Width);


             scale = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        o2.inScaled = false;
        return BitmapFactory.decodeFile(f.getAbsolutePath(),o2);
    } 
    catch(Exception e) 
    {
      e.printStackTrace();
    }
    return null;
}

它应该可以解决您的内存不足异常。 链接here对你的回答有很好的详细解释。

【讨论】:

  • 您能否解释一下这是在做什么以及为什么我要为与我的设备尺寸相同的 720 x 1280 图像执行此操作?
  • 看看这个,它非常有效地解释了这个问题。 developer.android.com/training/displaying-bitmaps/index.html
  • 上面的代码会对图像进行二次采样,将图像的较小版本加载到内存中。
  • @Panky90 您正在将缩小版本加载到内存中。您的位图可能太大,因此超出堆内存导致 OOM。
  • @Raghunandan 是的,这就是我发布的链接所说的内容,并且还详细回答了他的问题。
猜你喜欢
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多