概述
项目用到加载大图片,app老是出现OOM异常,总结了几点经验,供参考。
1、手动干涉dalvik的堆内存处理效率:
1 private final static float TARGET_HEAP_UTILIZATION = 0.75f; 2 //for same activity 3 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 activity 3 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 try 22 { 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 try 61 { 62 bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图 63 } catch (OutOfMemoryError e) 64 { 65 // TODO: handle exception 66 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 try 21 { 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 try 39 { 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 try 50 { 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.inSampleSize 59 + " 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 }
转载于:https://www.cnblogs.com/jevan/archive/2012/07/05/2577942.html
最后
以上就是儒雅金针菇为你收集整理的Android加载大图片OOM异常解决的全部内容,希望文章能够帮你解决Android加载大图片OOM异常解决所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复