Android加载大图片OOM异常解决

来源:互联网 发布:百度黑洞特效js 编辑:程序博客网 时间:2024/06/11 13:46

项目用到加载大图片,app老是出现OOM异常,总结了几点经验,供参考。

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

1     private final static float TARGET_HEAP_UTILIZATION = 0.75f;2     //for same activity3     public void onCreate()4     {5         …………6         VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 7         …………8     }

2、手动指定Android堆大小:

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

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

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

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

 1     /** 2      * @param url 3      *            图片的url 4      * @param sc 5      *            ,显示的像素大小 6      * @return 返回指定RUL的缩略图 7      *  8      * @author jevan 2012-7-3 9      * 10      */11     public static Bitmap loadImageFromUrl(String url, int sc)12     {13 14         URL m;15         InputStream i = null;16         BufferedInputStream bis = null;17         ByteArrayOutputStream out = null;18 19         if (url == null)20             return null;21         try22         {23             m = new URL(url);24             i = (InputStream) m.getContent();25             bis = new BufferedInputStream(i, 1024 * 4);26             out = new ByteArrayOutputStream();27             int len = 0;28 29             while ((len = bis.read(isBuffer)) != -1)30             {31                 out.write(isBuffer, 0, len);32             }33             out.close();34             bis.close();35         } catch (MalformedURLException e1)36         {37             e1.printStackTrace();38             return null;39         } catch (IOException e)40         {41             e.printStackTrace();42         }43         if (out == null)44             return null;45         byte[] data = out.toByteArray();46         BitmapFactory.Options options = new BitmapFactory.Options();47         options.inJustDecodeBounds = true;48         BitmapFactory.decodeByteArray(data, 0, data.length, options);49         options.inJustDecodeBounds = false;50         int be = (int) (options.outHeight / (float) sc);51         if (be <= 0)52         {53             be = 1;54         } else if (be > 3)55         {56             be = 3;57         }58         options.inSampleSize = be;59         Bitmap bmp =null;60         try61         {62             bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图63         } catch (OutOfMemoryError e)64         {65             // TODO: handle exception66             MainActivity.print("Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage()); 67         68             System.gc();69             bmp =null;70         }71         return bmp;72     }

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

 

以下内容为转载,收藏。

 1     //我们在BitmapManager.instance().decodeFile对图片进行解码,生成Bitmap的时候,我们会发现很多大图片会报OutOfMemoryError的错误,这个时候我们需要改变options里面的一些参数来解决这个问题,不然我们程序就跑不下去了。最简单的方法就是改变options.inSampleSize这个参数,把它增大,就可以解决很多图片OutOfMemoryError的问题。 2     //下面是一个使用了这个方式的代码 3     public static Bitmap makeBitmap(String path, int minSideLength, int maxNumOfPixels, BitmapFactory.Options options) 4     { 5         Bitmap b = null; 6         Log.i(TAG, "makeBitmap : path = " + path); 7         if (path == null) 8             return null; 9         File f = new File(path);10 11         //try {12         // b = BitmapManager.instance().decodeFile(f, null);13         //} catch (OutOfMemoryError ex) {14         // Log.e(TAG, "Got oom exception, we may try one more time, using Options:" + ex.getMessage());15         if (options == null)16         {17             options = new BitmapFactory.Options();18         }19 20         try21         {22             options.inJustDecodeBounds = true;23             BitmapManager.instance().decodeFile(f, options);24             if (options.mCancel || options.outWidth == -1 || options.outHeight == -1)25             {26                 return null;27             }28             options.inSampleSize = computeSampleSize(options, minSideLength, maxNumOfPixels);29             options.inJustDecodeBounds = false;30             options.inDither = true;31             options.inPreferredConfig = null;//Bitmap.Config.ARGB_8888;32 33             b = BitmapManager.instance().decodeFile(f, options);34         } catch (OutOfMemoryError ex2)35         {36             Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "37                     + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex2);38             try39             {40                 options.inSampleSize += 1;41                 options.inJustDecodeBounds = false;42                 options.inDither = true;43                 options.inPreferredConfig = null;44                 b = BitmapManager.instance().decodeFile(f, options);45             } catch (OutOfMemoryError e)46             {47                 Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "48                         + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, e);49                 try50                 {51                     options.inSampleSize += 1;52                     options.inJustDecodeBounds = false;53                     options.inDither = true;54                     options.inPreferredConfig = null;55                     b = BitmapManager.instance().decodeFile(f, options);56                 } catch (OutOfMemoryError ex)57                 {58                     Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize59                             + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex);60                     return null;61                 }62             }63         }64 65         //} 66         return b;67     }
 1     //另外一处代码 2     public static Bitmap getBitpMap(InputStream is) 3     { 4         ParcelFileDescriptor pfd; 5         try 6         { 7             pfd = getContentResolver().openFileDescriptor(uri, "r"); 8         } catch (IOException ex) 9         {10             return null;11         }12         java.io.FileDescriptor fd = pfd.getFileDescriptor();13         BitmapFactory.Options options = new BitmapFactory.Options();14         //先指定原始大小   15         options.inSampleSize = 1;16         //只进行大小判断   17         options.inJustDecodeBounds = true;18         //调用此方法得到options得到图片的大小   19         BitmapFactory.decodeFileDescriptor(fd, null, options);20         //BitmapFactory.decodeStream(is, null, options);21         //我们的目标是在800pixel的画面上显示。   22         //所以需要调用computeSampleSize得到图片缩放的比例   23         options.inSampleSize = computeSampleSize(options, 800);24         //OK,我们得到了缩放的比例,现在开始正式读入BitMap数据   25         options.inJustDecodeBounds = false;26         options.inDither = false;27         options.inPreferredConfig = Bitmap.Config.ARGB_8888;28 29         //根据options参数,减少所需要的内存   30         //        Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);31         Bitmap sourceBitmap = BitmapFactory.decodeStream(is, null, options);32         return sourceBitmap;33     }34 35     //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3   36     static int computeSampleSize(BitmapFactory.Options options, int target)37     {38         int w = options.outWidth;39         int h = options.outHeight;40         int candidateW = w / target;41         int candidateH = h / target;42         int candidate = Math.max(candidateW, candidateH);43         if (candidate == 0)44             return 1;45         if (candidate > 1)46         {47             if ((w > target) && (w / candidate) < target)48                 candidate -= 1;49         }50         if (candidate > 1)51         {52             if ((h > target) && (h / candidate) < target)53                 candidate -= 1;54         }55         //if (VERBOSE)56         Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w / candidate) + " / " + (h / candidate));57         return candidate;58     }

 

0 0