关于android中的图片缓冲区问题
来源:互联网 发布:取消地级市 知乎 编辑:程序博客网 时间:2024/05/17 00:18
关于android中的图片缓冲区问题
一个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;
- }
通过url去得到bitmap这个方法基本都是一致的,也许有的人写的强壮一点,功能会多一些。下边这个添加了附带cookies。其实多数时候是用不到的。
- /**
- * 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;
- }
在上边的方法里,可以看到有一个setLastModified(expiring, response);这个方法就是给bitmap这个数据添加上最后的修改时间,默认的会赋值成下载完成的时间,当二次访问的时候,我们可以重新赋值新的时间点。
- 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
- }
- }
从缓冲区中获取bitmap,这个方法基本都是给外部调用的,如果缓冲区存在这个bitmap,会返回,如果不存在就调用load(url)方法去获得这个bitmap数据并且放入缓冲区中。
- /**
- * 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;
- }
在文件的一开始,我们需要生成一个静态的缓冲区,一般都采用HashMap。
- 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);
- }
- }
这样一个简单的缓冲区文件基本雏形就有了,其他的需要自己按照自己的需求去写一下方法。或者进行一些有话,比如说这里提出的思路是每次读取一个bitmap时都会重置他的lastModified这个属性,然后在删除时,我们对这个属性进行遍历,删掉低于平均访问水瓶的bitmap,当然这个在以上程序代码中没有明确代码,因为以上代码是为了各自不同需求的基本代码,可以自己进行修改。对于前边这个思路的优化,可以删除掉lastModified这个属性,而采用一个队列的缓冲区方式,每次访问,都把这个bitmap先从队列中取出来,也就是删除,然后添加到队尾,这样的思路好处在于,当缓冲区多大,需要删除掉一些图片时,可以直接删除队首的若干个元素,节约了遍历所有元素的时间。
其他的对于缓冲区的使用还需要对线程进行一下控制,如果用的不好,也会出现一个线程的空间需求超出了分配给他的大小的异常。一般情况用线程池可以缓解这样的情况。
- 关于android中的图片缓冲区问题
- 关于缓冲区覆盖问题
- BufferedWriter中的缓冲区问题
- 关于scanf()的缓冲区问题
- 关于修复缓冲区溢出问题
- Android中的图片上传问题
- 获取IE缓冲区中的验证图片
- Unity中关于保存图片到Android/IOS相册中的问题
- 关于向Android项目中的drawable下添加图片却无法使用的问题
- 关于Android加载HTML页面中的图片显示问题的解决办法
- 关于Android Sutdio中的图片资源
- 关于缓冲区/池设计中的三个队列
- android关于手机拍照图片旋转问题
- 【转】关于scanf()的缓冲区问题
- 关于缓冲区的问题, 大家讨论一下.
- 关于Console.ReadLine()与缓冲区的问题
- 关于fork和缓冲区的问题
- Socket编程 关于缓冲区长度问题
- php 邮件接收代码,接收邮件处理主题和内容
- PHP学习笔记--ZendStudio的使用
- BMP格式
- 表格
- Oracle 建库方案
- 关于android中的图片缓冲区问题
- 提高php编程效率
- Perl中our,my,local的区别与联系
- 一切都忙碌起来了
- 校内上的脑残装X日志标题整理。
- 【USACO2.3.3】和为零
- QT signal & slot 定义及用法
- android中application共享数据以及内存泄露问题
- C# Winform 捕获窗体的最小化和最大化事件、关闭按钮事件 .