【OOM】Android加载大图片OOM异常解决


1、手动干涉dalvik的堆内存处理效率:

private final static float TARGET_HEAP_UTILIZATION = 0.75f;
     //for same activity
     public void onCreate()
     {
         …………
         VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 
         …………
     }


2、手动指定Android堆大小:

private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; 
     //for same activity
     public void onCreate()
     {
         …………
         VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理  
         …………
     }


3、手动指定回收内存,指定gc:

1         if(bitmap!=null && !bitmap.isRecycled())
2         {
3             bitmap.recycle();
4             System.gc();
5         }


4、图片必须进行缩放,不然多半会出OOM:

/**
      * @param url
      *            图片的url
      * @param sc
      *            ,显示的像素大小
      * @return 返回指定RUL的缩略图
      * 
      * @author jevan 2012-7-3
      * 
      */
     public static Bitmap loadImageFromUrl(String url, int sc)
     {
 
         URL m;
         InputStream i = null;
         BufferedInputStream bis = null;
         ByteArrayOutputStream out = null;
 
         if (url == null)
             return null;
         try
         {
             m = new URL(url);
             i = (InputStream) m.getContent();
             bis = new BufferedInputStream(i, 1024 * 4);
             out = new ByteArrayOutputStream();
             int len = 0;
 
             while ((len = bis.read(isBuffer)) != -1)
             {
                 out.write(isBuffer, 0, len);
             }
             out.close();
             bis.close();
         } catch (MalformedURLException e1)
         {
             e1.printStackTrace();
             return null;
         } catch (IOException e)
         {
             e.printStackTrace();
         }
         if (out == null)
             return null;
         byte[] data = out.toByteArray();
         BitmapFactory.Options options = new BitmapFactory.Options();
         options.inJustDecodeBounds = true;
         BitmapFactory.decodeByteArray(data, 0, data.length, options);
         options.inJustDecodeBounds = false;
         int be = (int) (options.outHeight / (float) sc);
         if (be <= 0)
         {
             be = 1;
         } else if (be > 3)
         {
             be = 3;
         }
         options.inSampleSize = be;
         Bitmap bmp =null;
         try
         {
             bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图
         } catch (OutOfMemoryError e)
         {
             // TODO: handle exception
             MainActivity.print("Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage()); 
         
             System.gc();
             bmp =null;
         }
         return bmp;
     }

 

把上面几条全部用上,OOM的异常基本上能完全避免!!!

以下内容为转载,收藏。

//我们在BitmapManager.instance().decodeFile对图片进行解码,生成Bitmap的时候,我们会发现很多大图片会报OutOfMemoryError的错误,这个时候我们需要改变options里面的一些参数来解决这个问题,不然我们程序就跑不下去了。最简单的方法就是改变options.inSampleSize这个参数,把它增大,就可以解决很多图片OutOfMemoryError的问题。
     //下面是一个使用了这个方式的代码
     public static Bitmap makeBitmap(String path, int minSideLength, int maxNumOfPixels, BitmapFactory.Options options)
     {
         Bitmap b = null;
         Log.i(TAG, "makeBitmap : path = " + path);
         if (path == null)
             return null;
         File f = new File(path);
 
         //try {
         // b = BitmapManager.instance().decodeFile(f, null);
         //} catch (OutOfMemoryError ex) {
         // Log.e(TAG, "Got oom exception, we may try one more time, using Options:" + ex.getMessage());
         if (options == null)
         {
             options = new BitmapFactory.Options();
         }
 
         try
         {
             options.inJustDecodeBounds = true;
             BitmapManager.instance().decodeFile(f, options);
             if (options.mCancel || options.outWidth == -1 || options.outHeight == -1)
             {
                 return null;
             }
             options.inSampleSize = computeSampleSize(options, minSideLength, maxNumOfPixels);
             options.inJustDecodeBounds = false;
             options.inDither = true;
             options.inPreferredConfig = null;//Bitmap.Config.ARGB_8888;
 
             b = BitmapManager.instance().decodeFile(f, options);
         } catch (OutOfMemoryError ex2)
         {
             Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
                     + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex2);
             try
             {
                 options.inSampleSize += 1;
                 options.inJustDecodeBounds = false;
                 options.inDither = true;
                 options.inPreferredConfig = null;
                 b = BitmapManager.instance().decodeFile(f, options);
             } catch (OutOfMemoryError e)
             {
                 Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
                         + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, e);
                 try
                 {
                     options.inSampleSize += 1;
                     options.inJustDecodeBounds = false;
                     options.inDither = true;
                     options.inPreferredConfig = null;
                     b = BitmapManager.instance().decodeFile(f, options);
                 } catch (OutOfMemoryError ex)
                 {
                     Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize
                             + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex);
                     return null;
                 }
             }
         }
 
         //} 
         return b;
     }


//另外一处代码

 public static Bitmap getBitpMap(InputStream is)
     {
         ParcelFileDescriptor pfd;
         try
         {
             pfd = getContentResolver().openFileDescriptor(uri, "r");
         } catch (IOException ex)
         {
             return null;
         }
         java.io.FileDescriptor fd = pfd.getFileDescriptor();
         BitmapFactory.Options options = new BitmapFactory.Options();
         //先指定原始大小   
         options.inSampleSize = 1;
         //只进行大小判断   
         options.inJustDecodeBounds = true;
         //调用此方法得到options得到图片的大小   
         BitmapFactory.decodeFileDescriptor(fd, null, options);
         //BitmapFactory.decodeStream(is, null, options);
         //我们的目标是在800pixel的画面上显示。   
         //所以需要调用computeSampleSize得到图片缩放的比例   
         options.inSampleSize = computeSampleSize(options, 800);
         //OK,我们得到了缩放的比例,现在开始正式读入BitMap数据   
         options.inJustDecodeBounds = false;
         options.inDither = false;
         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
 
         //根据options参数,减少所需要的内存   
         //        Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
         Bitmap sourceBitmap = BitmapFactory.decodeStream(is, null, options);
         return sourceBitmap;
     }
 
     //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3   
     static int computeSampleSize(BitmapFactory.Options options, int target)
     {
         int w = options.outWidth;
         int h = options.outHeight;
         int candidateW = w / target;
         int candidateH = h / target;
         int candidate = Math.max(candidateW, candidateH);
         if (candidate == 0)
             return 1;
         if (candidate > 1)
         {
             if ((w > target) && (w / candidate) < target)
                 candidate -= 1;
         }
         if (candidate > 1)
         {
             if ((h > target) && (h / candidate) < target)
                 candidate -= 1;
         }
         //if (VERBOSE)
         Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w / candidate) + " / " + (h / candidate));
         return candidate;
     }


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值