andorid批量处理 位图 报错 OutOfMemoryError: bitmap size exceeds VM budget

文章标签: android,outofmemoryerror
2014-12-27 22:49:03     人阅读    

 

我现在正在开发一个android app ,这个app有一个view包含了大量的图片,报错 内存溢出  java.lang.OutOfMemoryError: bitmap size exceeds VM budget

This is the stack trace
0       java.lang.OutOfMemoryError: bitmap size exceeds VM budget

1   at  android.graphics.Bitmap.nativeCreate(Native Method)
2   at  android.graphics.Bitmap.createBitmap(Bitmap.java:507)
3   at  android.graphics.Bitmap.createBitmap(Bitmap.java:474)
4   at  android.graphics.Bitmap.createScaledBitmap(Bitmap.java:379)
5   at  android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:498)
6   at  android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:473)
7   at  android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
8   at  android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:359)
9   at  android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:385)


我现在碰到的问题时,我无法重现这个问题...
我尝试了好多的方法去解决这个问题

1、没有内存泄漏:我确信是没有内存泄漏的。我在不需要视图的时候进行删除,并且循环删除掉了所有的位图。为确保垃圾收集器,我实现了所有的onDestroy()必要步骤方法
2、图像大小正确缩放:在开始讨论之前我的形象得到它的尺寸和计算inSampleSize。
3、堆大小:我也发现获得的图像前的最大堆大小,并确保有足够的空间。如果没有足够的内存我会重新缩放的图像。

下面代码是计算正确的 inSampleSize

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
   {
      // Raw height and width of image
      final int height = options.outHeight;
      final int width = options.outWidth;
      int inSampleSize = 1;

      if(height > reqHeight || width > reqWidth)
      {
         if(width > height)
         {
            inSampleSize = Math.round((float) height / (float) reqHeight);
         }
         else
         {
            inSampleSize = Math.round((float) width / (float) reqWidth);
         }
      }
      return inSampleSize;
   }

下面代码是获得 bitmap
// decodes image and scales it to reduce memory consumption
   private static Bitmap decodeFile(File file, int newWidth, int newHeight)
   {// target size
      try
      {

         Bitmap bmp = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), Uri.fromFile(file));
         if(bmp == null)
         {
            // avoid concurrence
            // Decode image size
            BitmapFactory.Options option = new BitmapFactory.Options();

            // option = getBitmapOutput(file);

            option.inDensity = res.getDisplayMetrics().densityDpi < DisplayMetrics.DENSITY_HIGH ? 120 : 240;
            option.inTargetDensity = res.getDisplayMetrics().densityDpi;

            if(newHeight > 0 && newWidth > 0)
                option.inSampleSize = calculateInSampleSize(option, newWidth, newWidth);

            option.inJustDecodeBounds = false;
            byte[] decodeBuffer = new byte[12 * 1024];
            option.inTempStorage = decodeBuffer;
            option.inPurgeable = true;
            option.inInputShareable = true;
            option.inScaled = true;

            bmp = BitmapFactory.decodeStream(new FileInputStream(file), null, option);
            if(bmp == null)
            {
               return null;
            }

         }
         else
         {
            int inDensity = res.getDisplayMetrics().densityDpi < DisplayMetrics.DENSITY_HIGH ? 120 : 240;
            int inTargetDensity = res.getDisplayMetrics().densityDpi;
            if(inDensity != inTargetDensity)
            {
               int newBmpWidth = (bmp.getWidth() * inTargetDensity) / inDensity;
               int newBmpHeight = (bmp.getHeight() * inTargetDensity) / inDensity;
               bmp = Bitmap.createScaledBitmap(bmp, newBmpWidth, newBmpHeight, true);
            }
         }

         return bmp;
      }
      catch(Exception e)
      {
         Log.e("Error calling Application.decodeFile Method params: " + Arrays.toString(new Object[]{file }), e);
      }
      return null;
   }

计算图片在Heap 中的大小(老设备)

private void calculateImagesSize()
   {
      // only for android older than HoneyComb that does not support large heap
      if(Build.VERSION.SDK_INT < Constants.HONEYCOMB)
      {
         long maxHeapSize = Runtime.getRuntime().maxMemory();
         long maxImageHeap = maxHeapSize - 10485760;
         if(Application.getResource().getDisplayMetrics().densityDpi >= DisplayMetrics.DENSITY_XHIGH)
         {
            maxImageHeap -= 12 * 1048576;
         }
         if(maxImageHeap < (30 * 1048576))
         {
            int screenHeight = Math.min(Application.getResource().getDisplayMetrics().heightPixels, Application.getResource()
               .getDisplayMetrics().widthPixels);
            long maxImageSize = maxImageHeap / 100;
            long maxPixels = maxImageSize / 4;
            long maxHeight = (long) Math.sqrt(maxPixels / 1.5);
            if(maxHeight < screenHeight)
            {
               drawableHeight = (int) maxHeight;
               drawableWidth = (int) (drawableHeight * 1.5);
            }
         }
      }
   }


我认为问题出在 Heap ,可能有一些时间系统不让app使用最大的 maxheapsize,我最大的问题时,这个问题只出现了一次,无法有效的重新....所以我不知道如何解决他....

 

处理方法

使用下面的函数来解码文件,可以完美解决你的问题,我以前也碰见过这个问题,就是这样解决的

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;
 }


原文地址:http://www.itmmd.com/201412/398.html
该文章由 萌萌的IT人 整理发布,转载须标明出处。

Volley JsonObjectRequest 请求发送失败   上一篇
下一篇  在Gradle 和 Android Studio中构建和运行app比在eclipse 中慢很多
精彩回复
我要追加问题,请求站长解决!
姓名:       

《程序员app》专门为程序员量身定做!