当你的应用由于加载大量图片出现OOM异常时,肯定会上网搜索关于OOM的文章,并导求相应的解决方案,比如压缩图片大小,或手动回收资源什么的。在这里我们不讨论图片压缩或缓冲这些方法,而是讨论一下手动回收BITMAP时可能出现的问题,亦即 Canvas: trying to use a recycled bitmap。

很容易可以预料到,你必然会遇到并使用如下代码:

  1. if(bitmap != null && !bitmap.isRecycled()){
  2. bitmap.recycle(); //此句造成的以上异常
  3. bitmap = null;
  4. }
  5. System.gc();

然后你将其添加到应用中,用着用着应用崩溃了,查一下LogCat日志,即出现了Canvas: trying to use a recycled bitmap类似的错误。

在进一步探讨之前,我们首先要提醒一下:Android本身就有资源回收机制,它的效果并不似他人所说的“不堪入目”,当你的程序运行时出现GC_CONCURRENT_XX时,说明系统正在回收资源。当然,前提是确实存在垃圾(亦即不再会被引用到的资源)。很多时候,你的应用程序出现OOM异常,是因为应用程序可能对大量的BITMAP资源都有引用,ANDROID自然不会去回收你可能会用到的资源,所以这个时候出现OOM是你的应用程序本身有些不完善,不能怪ANDROID。

一般来说,如果代码已经不再需要使用Bitmap对象了,就可以释放了。释放内存以后,就不能再使用该Bitmap对象了,如果再次使用,就会抛出异常。所以一定要保证不再使用的时候释放。比如,如果是在某个Activity中使用Bitmap,就可以在Activity的onStop()或者onDestroy()方法中进行回收。

那什么才是“不再需要使用的Bitmap对象”呢?废话,不就是后面用不到的图片资源呀,但实际使用的时候,你可能还是会遇到这个异常。其实只要注意BITMAP对象的引用后续是否可能会用到即可,即对象引用的特性!

比如,有同仁在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map<String, SoftReference<Bitmap>> imageCache , 并对其进行维护,在图片加载到一定数量的时候,就手动回收掉之前加载图片的bitmap,如果这个bitmap对象引用还会使用到,就会引起了这个错误。

如下所示:

public class TextBm{

private Bitmap bm;

public void setBitmap(Bitmap bm) {this.bm = bm;}

public Bitmap getBitmap(){return this.bm;}

}

TestBm test_bm = new TestBm();

test_bm.setBitmap(BitmapFactory.decodeFile(path1));

//其它更多代码

test_bm.setBitmap(BitmapFactory.decodeFile(path2));

当程序对TestBm的某个实例进行第二次赋值时,由于第一个Bitmap没有引用到,所以就成为垃圾,这个时候就可以在第二次赋值前用开头的回收代码进行回收。这个垃圾也会被ANROID系统自动回收,但不要小看这种垃圾,有些代码用定时刷新线程来做这样的赋值,产生很多垃圾,虽然系统能回收掉,但也会消耗很多时间,看看上图中的pause多少ms就知道了,那就是回收占用的时间。

再如下所示:

test_bm.setBitmap(imageCache.get(str1));//从图片缓存列表中取出1

//其它更多代码

test_bm.setBitmap(imageCache.get(str2));//从图片缓存列表中取出2

注意:这里第二次赋值时,第一个是有引用的(或者在更多其它地方使用过的),就是存在imageCache的Map中,如果你也像上面那样回收,就不是回收test_bm中bm成员的Bitmap1,而是将imageCache中的Bitmap1也给回收了,因为两个对象是同一个Bitmap1,这样一旦还有其它地方要使用,就会发生:

Canvas: trying to use a recycled bitmap

Android开发回收bitmap引发Canvas: trying to use a recycled bitmap错误处理的更多相关文章

  1. Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理

    在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map<String ...

  2. Android Bitmap操作问题之Canvas: trying to use a recycled bitmap

    一.Bitmap.recycle 方法被弃用 在Android中,Bitmap的存储分为两部分,一部分是Bitmap的数据,一部分是Bitmap的引用.在Android2.3时代,Bitmap的引用是 ...

  3. Canvas: trying to use a recycled bitmap android.graphics.Bitmap@XXX

    近期在做和图片相关显示的出现了一个问题,整理一下思路.分享出来给大家參考一下: Exception Type:java.lang.RuntimeException java.lang.RuntimeE ...

  4. 《android开发艺术探索》读书笔记(十二)--Bitmap的加载和Cache

    接上篇<android开发艺术探索>读书笔记(十一)--Android的线程和线程池 No1: 目前比较常用的缓存策略是LruCache和DiskLruCache,LruCache常被用作 ...

  5. Android开发艺术探索》读书笔记 (12) 第12章 Bitmap的加载和Cache

    第12章 Bitmap的加载和Cache 12.1 Bitmap的高速加载 (1)Bitmap是如何加载的?BitmapFactory类提供了四类方法:decodeFile.decodeResourc ...

  6. android 开发 View _12_ 用Canvas 绘制一张图片(博客中演示用Canvas画验证码图片)

    package net.yt.yuncare.widgets; import android.graphics.Bitmap; import android.graphics.Canvas; impo ...

  7. java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230

    近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...

  8. Android java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230

    近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...

  9. android开发里跳过的坑——“org.apache.http.message.BasicHeaderValueFormatter.INSTANCE”错误

    在android4.4.2的系统里,写了一个系统应用,其中有一个功能是通过表单上传图片的,使用了httpclient-4.5.3.jar httpmime-4.5.3.jar httpcore-4.4 ...

随机推荐

  1. ubuntu中执行可执行文件时报错“没有那个文件或目录”的解决办法(非权限问题)

    问题:可执行文件明明存在,也有可执行权限(x),但执行时就提示"没有那个文件或目录". 原因:这个程序的是32位的程序(比如arm-linux-gcc),而系统是64位的,运行时需 ...

  2. Alpha事后分析

    设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件的功能主要是让一些基于表单识别的项目(如微软智能表单识别项目)减少在数据生成方面上浪费的 ...

  3. 实施CRM系统后 企业客户服务的改变

    通过实施CRM客户管理系统,企业的竞争力和盈利能力得到大幅提高.在这个过程中,客户服务不仅能够持续的满足客户的需求,还能够促进客户与企业建立长期的互惠互利的良好客户关系,这也为企业赢得了更多的商机和利 ...

  4. Let's go!

    第一次开通博客 心情还是很激动的,而且做出了这么好看的页面虽然都是用的别人的组件,自己不是很知道原理但是也很开心,以后会将自己学习的东西写成笔记发在上面

  5. [Qt] 基本概念

    QObject :所有 Qt 类的基类 QWidget类:包含所有组件的类 Widgets:组件,组成Qt界面的基本元素 window:界面,是不含有父组件的组件 Child Widgets:子组件, ...

  6. QT相关书籍

    文章转载自:http://www.cctry.com/thread-290005-1-1.html 最近一段时间,陆陆续续给大家更新了不少基于Qt开发的不错的书籍,可以说每本都不错.不过放在这一堆大家 ...

  7. 【转载】]基于RedHatEnterpriseLinux V7(RHEL7)下SPEC CPU 2006环境搭建以及测试流程 介绍、安装准备、安装、config文件以及运行脚本介绍

    https://www.codetd.com/article/1137423 <版权声明:本文为博主原创文章,未经博主允许不得转载> 本次利用SPECCPU2006测试工具来进行Intel ...

  8. Docker——Tomcat JVM 内存配置

    前言 安装再docker中的tomcat,在下载大文件或者某些情况下,会出现tomcat的内存溢出等情况,所以需要配置tomcat的内存大小,docker中的tomcat内存大小配置有四种方式. 一. ...

  9. Chrome 红色和 Chromium蓝色 区别:logoChrome 红色和 Chromium蓝色;Chrome闭源和 Chromium开源;

    我们知道Chromium采用的BSD开源协议(Chromium首页.文档和下载),google chrome是闭源的("9.2 根据第 1.2 条规定,除非法律明确允许或要求,或经谷歌明确书 ...

  10. 云计算OpenStack共享组件---信息队列rabbitmq(2)

    一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 消息传 ...