Android开发回收bitmap引发Canvas: trying to use a recycled bitmap错误处理
当你的应用由于加载大量图片出现OOM异常时,肯定会上网搜索关于OOM的文章,并导求相应的解决方案,比如压缩图片大小,或手动回收资源什么的。在这里我们不讨论图片压缩或缓冲这些方法,而是讨论一下手动回收BITMAP时可能出现的问题,亦即 Canvas: trying to use a recycled bitmap。
很容易可以预料到,你必然会遇到并使用如下代码:
- if(bitmap != null && !bitmap.isRecycled()){
 - bitmap.recycle(); //此句造成的以上异常
 - bitmap = null;
 - }
 - 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错误处理的更多相关文章
- Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
		
在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map<String ...
 - Android Bitmap操作问题之Canvas: trying to use a recycled bitmap
		
一.Bitmap.recycle 方法被弃用 在Android中,Bitmap的存储分为两部分,一部分是Bitmap的数据,一部分是Bitmap的引用.在Android2.3时代,Bitmap的引用是 ...
 - Canvas: trying to use a recycled bitmap android.graphics.Bitmap@XXX
		
近期在做和图片相关显示的出现了一个问题,整理一下思路.分享出来给大家參考一下: Exception Type:java.lang.RuntimeException java.lang.RuntimeE ...
 - 《android开发艺术探索》读书笔记(十二)--Bitmap的加载和Cache
		
接上篇<android开发艺术探索>读书笔记(十一)--Android的线程和线程池 No1: 目前比较常用的缓存策略是LruCache和DiskLruCache,LruCache常被用作 ...
 - Android开发艺术探索》读书笔记 (12) 第12章 Bitmap的加载和Cache
		
第12章 Bitmap的加载和Cache 12.1 Bitmap的高速加载 (1)Bitmap是如何加载的?BitmapFactory类提供了四类方法:decodeFile.decodeResourc ...
 - android 开发 View _12_ 用Canvas 绘制一张图片(博客中演示用Canvas画验证码图片)
		
package net.yt.yuncare.widgets; import android.graphics.Bitmap; import android.graphics.Canvas; impo ...
 - java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230
		
近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...
 - Android java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230
		
近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...
 - android开发里跳过的坑——“org.apache.http.message.BasicHeaderValueFormatter.INSTANCE”错误
		
在android4.4.2的系统里,写了一个系统应用,其中有一个功能是通过表单上传图片的,使用了httpclient-4.5.3.jar httpmime-4.5.3.jar httpcore-4.4 ...
 
随机推荐
- Nifi:初识nifi
			
写在前面: 第一次接触这一系统的时候,只有github上的一坨源码和官方的英文文档,用起来只能说是一步一个坑,一踩一个脚印,现在回想那段血泪史,只想 ***,现在用起来算是有了一些经验和总结,这里就做 ...
 - 名称空间 反向解析 reverse
 - 风变编程(Python自学笔记)第11关-杀死那只“机”生虫
			
1.Debug:为程序排除错误. 2.SyntaxError:语法错误. 3.append()函数是列表的一个方法,要用句点.调用,且append()每次只能接受一个参数. 4.解决思路不清的两个工具 ...
 - Servlet-授课
			
1 Servlet 1.1 Servlet概述 Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一.我们可以像学习Java基础一样,通过API来学习Ser ...
 - [bug] Authentication failed for token submission (认证失败)异常
			
原因 gitee上下的项目,启动后能访问首页,但登录报错.原因是根据用户名上数据库查密码没有得到结果,中间任何环节有问题都可能导致,我的是因为mapper.xml中的<mapper namesp ...
 - 【转载】基于Linux命令行KVM虚拟机的安装配置与基本使用
			
基于Linux命令行KVM虚拟机的安装配置与基本使用 https://alex0227.github.io/2018/06/06/%E5%9F%BA%E4%BA%8ELinux%E5%91%BD%E4 ...
 - Win10屏幕亮度不能调节,调节无效怎么办?
			
Win10屏幕亮度不能调节,调节无效怎么办? 听语音 浏览:1027 | 更新:2019-11-22 11:43 1 2 3 4 5 6 7 分步阅读 一些用户在使用win10系统之后,出现了电脑屏幕 ...
 - Hive 默认分隔符
			
引言 Hive 中的默认分隔符是 ^A (\001) ,这是一种特殊的分隔符,使用的是 ASCII 编码的值,键盘是打不出来的 查看 Hive 默认分隔符文件 Linux 上的文件 以 \001 作为 ...
 - Swift系列十 - inout的本质
			
inout是可以用来在函数内部修改外部属性内存的. 一.inout回顾 示例代码: func test(_ num: inout Int) { num = 20 } var a = 10 test(& ...
 - Servlet中的过滤器和监听器
			
1.什么是过滤器? Servlet规范中定义的一种特殊的组件,用来拦截容器的调用过程.容器收到请求之后,首先调用过滤器,然后再调用Servlet 2.生命周期: 1.servlet:servlet的生 ...