一个关于OutOfMemoryError的处理【转载】谢谢网络上大神们
2014-11-05 15:31
531 查看
原文:http://blog.sina.com.cn/s/blog_73e890f401016nmw.html
前些日子一直为图片内存溢出问题困扰着,查了N多资料,将google彻底翻遍了都没找到解决方案,就当我几乎绝望的时候意外发现了一位网友的一个工具类,抱着最后一丝希望将代码co过来试了一把,结果令我喜出望外。嘿,解决了!暂不说多么欢喜了,听我慢慢道来这其中的前因后果吧!
需求:下载时候将图片一并down下来,在空间里显示并支持离线观看
第一个版本代码:
问题出现了,由于显示的图片过大,所以会出现OutOfMemoryException。我就设想能否捕捉异常来回收图片再重新加载,于是欲从网上找解决办法,什么手动干预GC,什么将图片弱化什么使用弱引用保存图片,有些总结得特别好(/article/4316713.html),这些方法我一一尝试可问题仍然未解决。不断的OOM,不断的尝试recycle,错误倒是不出现,可一旦内存吃不消就会显示不了图片,出现的都是默认图片。最终我从网上找到如下工具类,助我很好的解决了此问题,具体网址忘记了(得谢谢那位网友啦(*^__^*)),现在代码贴出来以便下次顺手拈来
在使用时我只调用了getBitmap方法,将需要设置的高度宽度以及本地图片路径传递过去就能自动返回bitmap给我,而且当捕捉到OOMError的时候将LinkedList的最后一张图片也就是最先存的图片进行溢出并回收就大功告成,特别注意的是这里捕捉错误Exception是获取不到的,一定要手动捕获OutOfMemoryError你才能进行处理(估计这些道理大家都懂得,所以不赘述啦,童鞋们加油!办法总比困难多o(∩_∩)o)
前些日子一直为图片内存溢出问题困扰着,查了N多资料,将google彻底翻遍了都没找到解决方案,就当我几乎绝望的时候意外发现了一位网友的一个工具类,抱着最后一丝希望将代码co过来试了一把,结果令我喜出望外。嘿,解决了!暂不说多么欢喜了,听我慢慢道来这其中的前因后果吧!
需求:下载时候将图片一并down下来,在空间里显示并支持离线观看
第一个版本代码:
//从本地读取图片 publicBitmap getBitmapFromSD(String filename) { FileInputStream fi = null; BufferedInputStream bi = null; Bitmap bp = null; try { fi = new FileInputStream(filename); bi = new BufferedInputStream(fi); bp = BitmapFactory.decodeStream(bi); } catch (IOException e) { bp = null; } finally { try { if (bi != null) { bi.close(); } if (fi != null) { fi.close(); } } catch (IOException e) { bp = null; } } return bp; }
问题出现了,由于显示的图片过大,所以会出现OutOfMemoryException。我就设想能否捕捉异常来回收图片再重新加载,于是欲从网上找解决办法,什么手动干预GC,什么将图片弱化什么使用弱引用保存图片,有些总结得特别好(/article/4316713.html),这些方法我一一尝试可问题仍然未解决。不断的OOM,不断的尝试recycle,错误倒是不出现,可一旦内存吃不消就会显示不了图片,出现的都是默认图片。最终我从网上找到如下工具类,助我很好的解决了此问题,具体网址忘记了(得谢谢那位网友啦(*^__^*)),现在代码贴出来以便下次顺手拈来
publicfinal class BitMapUtil { private static final Size ZERO_SIZE = new Size(0, 0); privatestatic final Options OPTIONS_GET_SIZE = new Options(); private static final Options OPTIONS_DECODE = new Options(); private static final byte[] LOCKED = new byte[0]; // 此对象用来保持Bitmap的回收顺序,保证最后使用的图片被回收 private static final LinkedList CACHE_ENTRIES = newLinkedList(); // 线程请求创建图片的队列 private static final Queue TASK_QUEUE = newLinkedList(); // 保存队列中正在处理的图片的key,有效防止重复添加到请求创建队列 private static final Set TASK_QUEUE_INDEX = newHashSet(); // 缓存Bitmap private static final Map IMG_CACHE_INDEX = newHashMap(); //通过图片路径,图片大小 privatestatic int CACHE_SIZE = 20; // 缓存图片数量 static { OPTIONS_GET_SIZE.inJustDecodeBounds = true; // 初始化创建图片线程,并等待处理 new Thread() { { setDaemon(true); } publicvoid run() { while(true) { synchronized(TASK_QUEUE) { if(TASK_QUEUE.isEmpty()) { try{ TASK_QUEUE.wait(); }catch (InterruptedException e) { e.printStackTrace(); } } } QueueEntryentry = TASK_QUEUE.poll(); Stringkey = createKey(entry.path, entry.width, entry.height); TASK_QUEUE_INDEX.remove(key); createBitmap(entry.path,entry.width, entry.height); } } }.start(); } public static Bitmap getBitmap(String path, intwidth, int height) { if(path==null){ return null; } Bitmap bitMap = null; try { if(CACHE_ENTRIES.size() >= CACHE_SIZE) { destoryLast(); } bitMap =useBitmap(path, width, height); if (bitMap !=null && !bitMap.isRecycled()) { returnbitMap; } bitMap =createBitmap(path, width, height); String key =createKey(path, width, height); synchronized(LOCKED) { IMG_CACHE_INDEX.put(key,bitMap); CACHE_ENTRIES.addFirst(key); } } catch (OutOfMemoryError err){ destoryLast(); System.out.println(CACHE_SIZE); returncreateBitmap(path, width, height); } return bitMap; } public static Size getBitMapSize(String path){ File file = newFile(path); if (file.exists()) { InputStreamin = null; try { in= new FileInputStream(file); BitmapFactory.decodeStream(in,null, OPTIONS_GET_SIZE); returnnew Size(OPTIONS_GET_SIZE.outWidth, OPTIONS_GET_SIZE.outHeight); } catch(FileNotFoundException e) { returnZERO_SIZE; } finally{ closeInputStream(in); } } return ZERO_SIZE; } //------------------------------------------------------------------private Methods // 将图片加入队列头 private static Bitmap useBitmap(String path, intwidth, int height) { Bitmap bitMap = null; String key = createKey(path,width, height); synchronized (LOCKED) { bitMap =IMG_CACHE_INDEX.get(key); if (null !=bitMap) { if(CACHE_ENTRIES.remove(key)) { CACHE_ENTRIES.addFirst(key); } } } return bitMap; } // 回收最后一张图片 private static void destoryLast() { synchronized (LOCKED) { String key =CACHE_ENTRIES.removeLast(); if(key.length() > 0) { BitmapbitMap = IMG_CACHE_INDEX.remove(key); if(bitMap != null && !bitMap.isRecycled()) { bitMap.recycle(); bitMap= null; } } } } // 创建键 private static String createKey(String path, intwidth, int height) { if (null == path ||path.length() == 0) { return""; } return path + "_" + width + "_"+ height; } // 通过图片路径,宽度高度创建一个Bitmap对象 private static Bitmap createBitmap(String path,int width, int height) { File file = newFile(path); if (file.exists()) { InputStreamin = null; try { in= new FileInputStream(file); Sizesize = getBitMapSize(path); if(size.equals(ZERO_SIZE)) { returnnull; } intscale = 1; inta = size.getWidth() / width; intb = size.getHeight() / height; scale= Math.max(a, b); synchronized(OPTIONS_DECODE) { OPTIONS_DECODE.inSampleSize= scale; BitmapbitMap = BitmapFactory.decodeStream(in, null, OPTIONS_DECODE); returnbitMap; } } catch(FileNotFoundException e) { Log.v("BitMapUtil","createBitmap=="+e.toString()); } finally{ closeInputStream(in); } } return null; } // 关闭输入流 private static void closeInputStream(InputStreamin) { if (null != in) { try { in.close(); } catch(IOException e) { Log.v("BitMapUtil","closeInputStream=="+e.toString()); } } } // 图片大小 static class Size { private int width, height; Size(int width, int height){ this.width =width; this.height =height; } public int getWidth(){ returnwidth; } public int getHeight(){ returnheight; } } // 队列缓存参数对象 static class QueueEntry { public String path; public int width; public int height; } }
在使用时我只调用了getBitmap方法,将需要设置的高度宽度以及本地图片路径传递过去就能自动返回bitmap给我,而且当捕捉到OOMError的时候将LinkedList的最后一张图片也就是最先存的图片进行溢出并回收就大功告成,特别注意的是这里捕捉错误Exception是获取不到的,一定要手动捕获OutOfMemoryError你才能进行处理(估计这些道理大家都懂得,所以不赘述啦,童鞋们加油!办法总比困难多o(∩_∩)o)
相关文章推荐
- 关于java.lang.outofmemoryerror的报错处理
- 关于java.lang.outofmemoryerror的报错处理
- 关于OutOfMemoryError的处理
- 不同平台下处理【java.lang.OutOfMemoryError: Java heap space】内存溢出。
- java.lang.OutOfMemoryError : Java heap space 及其处理
- 关于java.lang.OutOfMemoryError:java heap space错误解决方案
- 关于SSH部署到tomcat时OutOfMemoryError 的解决办法
- java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
- java.lang.OutOfMemoryError: Java heap space错误及处理办法
- java.lang.OutOfMemoryError: Java heap space错误处理办法之一
- java.lang.OutOfMemoryError: Java heap space错误及处理方法
- java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
- java错误处理:java.lang.OutOfMemoryError: Java heap space
- 图片的cache处理时出现内存溢出(OutOfMemoryError, OutOfMemory)的解决方法
- java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
- (转)java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
- 一篇关于“java.lang.OutOfMemoryError: PermGen space”的资料
- [转载]java.lang.OutOfMemoryError: PermGen space及其解决方法
- java.lang.OutOfMemoryError: Java heap space错误及处理办法(收集整理、转)
- [转载]java.lang.OutOfMemoryError: bitmap size exceeds VM budget解决方法