关于android中的图片缓冲区问题
android中的图片缓冲区一直是个问题,包括超出虚拟机所分配的资源上限,重用已回收的bitmap等等,解决这个问题,每个人有每个人不同的方式,这里记录下我在项目中学到的的图片缓冲区的实现方式。
一个bitmap,可以携带一个属性,标识着这个bitmap最后的使用时间。而我们如果创建一个缓冲区,这个区里的bitmap数量是有一定限制的,否则就会出现内存溢出,超出了虚拟机分给程序的内存空间。而这个bitmap的最后使用时间就是确定删不删除这个bitmap的标志。
/** * A Bitmap associated with its last modification date. This can be used to check * whether the book covers should be downloaded again. */ public static class ExpiringBitmap { public Bitmap bitmap; public Calendar lastModified; } /** * Loads an image from the specified URL with the specified cookie. * * @param url The URL of the image to load. * @param cookie The cookie to use to load the image. * * @return The image at the specified URL or null if an error occured. */ public static ExpiringBitmap load(String url, String cookie) { ExpiringBitmap expiring = new ExpiringBitmap(); final HttpGet get = new HttpGet(url); if (cookie != null) get.setHeader("cookie", cookie); HttpEntity entity = null; try { final HttpResponse response = HttpManager.execute(get); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { setLastModified(expiring, response); entity = response.getEntity(); InputStream in = null; OutputStream out = null; try { in = entity.getContent(); if (FLAG_DECODE_BITMAP_WITH_SKIA) { expiring.bitmap = BitmapFactory.decodeStream(in); } else { final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); out = new BufferedOutputStream(dataStream, IOUtilities.IO_BUFFER_SIZE); IOUtilities.copy(in, out); out.flush(); final byte[] data = dataStream.toByteArray(); expiring.bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); } } catch (IOException e) { android.util.Log.e(LOG_TAG, "Could not load image from " + url, e); } finally { IOUtilities.closeStream(in); IOUtilities.closeStream(out); } } } catch (IOException e) { android.util.Log.e(LOG_TAG, "Could not load image from " + url, e); } finally { if (entity != null) { try { entity.consumeContent(); } catch (IOException e) { android.util.Log.e(LOG_TAG, "Could not load image from " + url, e); } } } return expiring; }private static void setLastModified(ExpiringBitmap expiring, HttpResponse response) { expiring.lastModified = null; final Header header = response.getFirstHeader("Last-Modified"); if (header == null) return; if (sLastModifiedFormat == null) { sLastModifiedFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); } final Calendar calendar = GregorianCalendar.getInstance(); try { calendar.setTime(sLastModifiedFormat.parse(header.getValue())); expiring.lastModified = calendar; } catch (ParseException e) { // Ignore } } /** * Retrieves a drawable from the book covers cache, identified by the specified id. * If the drawable does not exist in the cache, it is loaded and added to the cache. * If the drawable cannot be added to the cache, the specified default drwaable is * returned. * * @param id The id of the drawable to retrieve * @param defaultCover The default drawable returned if no drawable can be found that * matches the id * * @return The drawable identified by id or defaultCover */ public static FastBitmapDrawable getCachedCover(String id, FastBitmapDrawable defaultCover) { FastBitmapDrawable drawable = null; SoftReference<FastBitmapDrawable> reference = sArtCache.get(id); if (reference != null) { drawable = reference.get(); } if (drawable == null) { final Bitmap bitmap = loadCover(id); if (bitmap != null) { drawable = new FastBitmapDrawable(bitmap); } else { drawable = NULL_DRAWABLE; } sArtCache.put(id, new SoftReference<FastBitmapDrawable>(drawable)); } return drawable == NULL_DRAWABLE ? defaultCover : drawable; }private static final HashMap<String, SoftReference<FastBitmapDrawable>> sArtCache = new HashMap<String, SoftReference<FastBitmapDrawable>>();
/** * Removes all the callbacks from the drawables stored in the memory cache. This * method must be called from the onDestroy() method of any activity using the * cached drawables. Failure to do so will result in the entire activity being * leaked. */ public static void cleanupCache() { for (SoftReference<FastBitmapDrawable> reference : sArtCache.values()) { final FastBitmapDrawable drawable = reference.get(); if (drawable != null) drawable.setCallback(null); } }