android端读取本地图片出现OutOfMemoryException解决办法
前些日子一直为图片内存溢出问题困扰着,查了N多资料,将google彻底翻遍了都没找到解决方案,就当我几乎绝望的时候意外发现了一位网友的一个工具类,抱着最后一丝希望将代码co过来试了一把,结果令我喜出望外。嘿,解决了!暂不说多么欢喜了,听我慢慢道来这其中的前因后果吧!
//从本地读取图片 public Bitmap 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; }
public final class BitMapUtil { private static final Size ZERO_SIZE = new Size(0, 0); private static 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 = new LinkedList(); // 线程请求创建图片的队列 private static final Queue TASK_QUEUE = new LinkedList(); // 保存队列中正在处理的图片的key,有效防止重复添加到请求创建队列 private static final Set TASK_QUEUE_INDEX = new HashSet(); // 缓存Bitmap private static final Map IMG_CACHE_INDEX = new HashMap(); // 通过图片路径,图片大小 private static int CACHE_SIZE = 20; // 缓存图片数量 static { OPTIONS_GET_SIZE.inJustDecodeBounds = true; // 初始化创建图片线程,并等待处理 new Thread() { { setDaemon(true); } public void run() { while (true) { synchronized (TASK_QUEUE) { if (TASK_QUEUE.isEmpty()) { try { TASK_QUEUE.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } QueueEntry entry = TASK_QUEUE.poll(); String key = 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, int width, 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()) { return bitMap; } 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); return createBitmap(path, width, height); } return bitMap; } public static Size getBitMapSize(String path) { File file = new File(path); if (file.exists()) { InputStream in = null; try { in = new FileInputStream(file); BitmapFactory.decodeStream(in, null, OPTIONS_GET_SIZE); return new Size(OPTIONS_GET_SIZE.outWidth, OPTIONS_GET_SIZE.outHeight); } catch (FileNotFoundException e) { return ZERO_SIZE; } finally { closeInputStream(in); } } return ZERO_SIZE; } // ------------------------------------------------------------------ private Methods // 将图片加入队列头 private static Bitmap useBitmap(String path, int width, 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) { Bitmap bitMap = IMG_CACHE_INDEX.remove(key); if (bitMap != null && !bitMap.isRecycled()) { bitMap.recycle(); bitMap = null; } } } } // 创建键 private static String createKey(String path, int width, 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 = new File(path); if (file.exists()) { InputStream in = null; try { in = new FileInputStream(file); Size size = getBitMapSize(path); if (size.equals(ZERO_SIZE)) { return null; } int scale = 1; int a = size.getWidth() / width; int b = size.getHeight() / height; scale = Math.max(a, b); synchronized (OPTIONS_DECODE) { OPTIONS_DECODE.inSampleSize = scale; Bitmap bitMap = BitmapFactory.decodeStream(in, null, OPTIONS_DECODE); return bitMap; } } catch (FileNotFoundException e) { Log.v("BitMapUtil","createBitmap=="+e.toString()); } finally { closeInputStream(in); } } return null; } // 关闭输入流 private static void closeInputStream(InputStream in) { 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() { return width; } public int getHeight() { return height; } } // 队列缓存参数对象 static class QueueEntry { public String path; public int width; public int height; } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。