当你的应用由于加载大量图片出现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. 技术博客:Azure Functions + Azure Storage 开发

    Azure GitHub wiki 同步发布 传送门 Azure Functions 通过 Functions(一个事件驱动型无服务器计算平台,还可以解决复杂的业务流程问题)更加高效地进行开发.在本地 ...

  2. python 键盘中断子线程及graceful exiting方案

    最近需要实现一个服务程序的graceful exiting,保证在退出前关闭所有已创建的子线程 python借助KeyboardInterrupted异常响应键盘中断,因此首先尝试在子线程中try-c ...

  3. 阿里云RDS数据库到期实例被清除,别急着哭(阿里没有删库跑路),或许还有一线生机

    阿里资源到期未续费,数据保存期限: ECS实例的保存期是15天. Redis实例的保存期是7天. RDS实例的保存期也是7天. 过期当天会收到一条短信: [阿里云]尊敬的用户:您的RDS实例(实例ID ...

  4. Word·去掉复制粘贴自动添加的空格

    阅文时长 | 0.05分钟 字数统计 | 145.6字符 主要内容 | 1.引言&背景 2.声明与参考资料 『Word·去掉复制粘贴自动添加的空格』 编写人 | SCscHero 编写时间 | ...

  5. ]# dmesg | grep ATAcentos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信息

    centos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信息 osc_4o5tc4xq 2019/10/11 15:03 阅读数 253 centos下查看网卡,主板,CPU,显卡,硬盘型号等硬件信 ...

  6. Linux巡检常用命令

    # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostn ...

  7. Java求余%引发的一连串故事

    C1 RCE对%的处理 HotSpot VM的C1有个RCE(Range Check Elimination,范围检查消除)优化,所谓范围检查消除,就是为了正确的抛出数组越界异常,虚拟机需要在数组访问 ...

  8. Python小白的数学建模课-A1.2021年数维杯C题(运动会优化比赛模式探索)探讨

    Python小白的数学建模课 A1-2021年数维杯C题(运动会优化比赛模式探索)探讨. 运动会优化比赛模式问题,是公平分配问题 『Python小白的数学建模课 @ Youcans』带你从数模小白成为 ...

  9. GO学习-(15) Go语言基础之包

    Go语言基础之包 在工程化的Go语言开发项目中,Go语言的源码复用是建立在包(package)基础之上的.本文介绍了Go语言中如何定义包.如何导出包的内容及如何导入其他包. Go语言的包(packag ...

  10. Mysql索引创建及删除

    1.索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的My ...