java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@358df999

简介: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@358df999

在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map> imageCache , 并对其进行维护,在图片加载到一定数量的时候,就手动回收掉之前加载图片的bitmap,此时就引起了如下错误:

Java代码  


  1. java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41de4380  
  2.    at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)  
  3.    at android.graphics.Canvas.drawBitmap(Canvas.java:1127)  
  4.    at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)  
  5.    at android.widget.ImageView.onDraw(ImageView.java:961)  
  6.    at android.view.View.draw(View.java:13458)  
  7.    at android.view.View.draw(View.java:13342)  
  8.    at android.view.ViewGroup.drawChild(ViewGroup.java:2929)  
  9.    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)  
  10.    at android.view.View.draw(View.java:13461)  
  11.    at android.view.View.draw(View.java:13342)  

图片手动回收部分代码:

Java代码  


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

网上有好多人说应该把recycle()去掉,个人认为去掉后会引起内存持续增长,虽然将bitmap设置为了null,但是系统并没有对其进行真正的回收,仍然占有内存,即是调用了System.gc() 强制回后以后,内存仍然没有下去,如果依靠内存达到上限时系统自己回收的话,个人觉得太晚了,已经对应用造成了影响,应用应该是比较卡了,所以还是赞同加上bitmap.recycle() ,但是又会引起 Canvas: trying to use a recycled bitmap 异常,困扰了很久,开始尝试从其它方面着手来解决这个问题,即然是异常就应该能够捕获到,但是在Adapter里的getView()方法里进行捕获的时候,时机晚了,没有捕获到。现在换到在ImageViewonDraw()里进行捕获,上面的异常能够捕获。

解决方法(继承ImageView 重写onDraw()方法,捕获异常):

在重写onDraw()方法中,其实什么都没有做,只是添加了一个异常捕获,即可捕捉到上面的错误

Java代码  


  1. import android.content.Context;  
  2. import android.graphics.Canvas;  
  3. import android.util.AttributeSet;  
  4. import android.widget.ImageView;  
  5.  
  6. /**
  7. * 重写ImageView,避免引用已回收的bitmap异常
  8. *
  9. * @author zwn
  10. *
  11. */  
  12. publicclass MyImageView extends ImageView {  
  13.  
  14.    public MyImageView (Context context, AttributeSet attrs) {  
  15.        super(context, attrs);  
  16.    }  
  17.  
  18.    @Override  
  19.    protectedvoid onDraw(Canvas canvas) {  
  20.        try {  
  21.            super.onDraw(canvas);  
  22.        } catch (Exception e) {  
  23.            System.out  
  24.                    .println("MyImageView  -> onDraw() Canvas: trying to use a recycled bitmap");  
  25.        }  
  26.    }  
  27.  
  28. }  

在做Android的开发的时候,在ListView 或是 GridView中需要加载大量的图片,为了避免加载过多的图片引起OutOfMemory错误,设置了一个图片缓存列表 Map> imageCache , 并对其进行维护,在图片加载到一定数量的时候,就手动回收掉之前加载图片的bitmap,此时就引起了如下错误:

Java代码  


  1. java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41de4380  
  2.    at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)  
  3.    at android.graphics.Canvas.drawBitmap(Canvas.java:1127)  
  4.    at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)  
  5.    at android.widget.ImageView.onDraw(ImageView.java:961)  
  6.    at android.view.View.draw(View.java:13458)  
  7.    at android.view.View.draw(View.java:13342)  
  8.    at android.view.ViewGroup.drawChild(ViewGroup.java:2929)  
  9.    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)  
  10.    at android.view.View.draw(View.java:13461)  
  11.    at android.view.View.draw(View.java:13342)  

图片手动回收部分代码:

Java代码  


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

网上有好多人说应该把recycle()去掉,个人认为去掉后会引起内存持续增长,虽然将bitmap设置为了null,但是系统并没有对其进行真正的回收,仍然占有内存,即是调用了System.gc() 强制回后以后,内存仍然没有下去,如果依靠内存达到上限时系统自己回收的话,个人觉得太晚了,已经对应用造成了影响,应用应该是比较卡了,所以还是赞同加上bitmap.recycle() ,但是又会引起 Canvas: trying to use a recycled bitmap 异常,困扰了很久,开始尝试从其它方面着手来解决这个问题,即然是异常就应该能够捕获到,但是在Adapter里的getView()方法里进行捕获的时候,时机晚了,没有捕获到。现在换到在ImageViewonDraw()里进行捕获,上面的异常能够捕获。

解决方法(继承ImageView 重写onDraw()方法,捕获异常):

在重写onDraw()方法中,其实什么都没有做,只是添加了一个异常捕获,即可捕捉到上面的错误

Java代码  


  1. import android.content.Context;  
  2. import android.graphics.Canvas;  
  3. import android.util.AttributeSet;  
  4. import android.widget.ImageView;  
  5.  
  6. /**
  7. * 重写ImageView,避免引用已回收的bitmap异常
  8. *
  9. * @author zwn
  10. *
  11. */  
  12. publicclass MyImageView extends ImageView {  
  13.  
  14.    public MyImageView (Context context, AttributeSet attrs) {  
  15.        super(context, attrs);  
  16.    }  
  17.  
  18.    @Override  
  19.    protectedvoid onDraw(Canvas canvas) {  
  20.        try {  
  21.            super.onDraw(canvas);  
  22.        } catch (Exception e) {  
  23.            System.out  
  24.                    .println("MyImageView  -> onDraw() Canvas: trying to use a recycled bitmap");  
  25.        }  
  26.    }  
  27.  
  28. }  
相关文章
|
23天前
|
存储 Java
Bitmap位图(Java实现)
本文介绍了使用Java实现一个简单的Bitmap,通过自定义byte数组存储数据,提供put和exist方法分别用于插入数据和查询数据是否存在。Bitmap利用位操作高效地管理大量布尔值,适用于空间优化的场景。代码中详细解释了位图的核心原理、方法实现及边界检查。后续计划探讨位图在海量数据去重中的应用及JDK BitSet源码分析。
57 7
|
3月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
170 1
|
4月前
|
Java 调度 Android开发
Android经典实战之Kotlin的delay函数和Java中的Thread.sleep有什么不同?
本文介绍了 Kotlin 中的 `delay` 函数与 Java 中 `Thread.sleep` 方法的区别。两者均可暂停代码执行,但 `delay` 适用于协程,非阻塞且高效;`Thread.sleep` 则阻塞当前线程。理解这些差异有助于提高程序效率与可读性。
87 1
|
4月前
|
Android开发
Cannot create android app from an archive...containing both DEX and Java-bytecode content
Cannot create android app from an archive...containing both DEX and Java-bytecode content
48 2
|
5月前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
【7月更文挑战第28天】在 Android 开发中, NDK 让 Java 与 C++ 混合编程成为可能, 从而提升应用性能。**为何选 NDK?** C++ 在执行效率与内存管理上优于 Java, 特别适合高性能需求场景。**环境搭建** 需 Android Studio 和 NDK, 工具如 CMake。**JNI** 构建 Java-C++ 交互, 通过声明 `native` 方法并在 C++ 中实现。**实战** 示例: 使用 C++ 计算斐波那契数列以提高效率。**总结** 混合编程增强性能, 但增加复杂性, 使用前需谨慎评估。
154 4
|
5月前
|
存储 NoSQL Java
Java中使用redis的bitMap实现签到功能
这个实现示例提供了一种灵活、高效的方式,展示了如何使用Redis来解决现实中的问题。
335 2
|
5月前
|
SQL Java Unix
Android经典面试题之Java中获取时间戳的方式有哪些?有什么区别?
在Java中获取时间戳有多种方式,包括`System.currentTimeMillis()`(毫秒级,适用于日志和计时)、`System.nanoTime()`(纳秒级,高精度计时)、`Instant.now().toEpochMilli()`(毫秒级,ISO-8601标准)和`Instant.now().getEpochSecond()`(秒级)。`Timestamp.valueOf(LocalDateTime.now()).getTime()`适用于数据库操作。选择方法取决于精度、用途和时间起点的需求。
76 3
|
6月前
|
安全 Java 编译器
Android面试题之Java 泛型和Kotlin泛型
**Java泛型是JDK5引入的特性,用于编译时类型检查和安全。泛型擦除会在运行时移除类型参数,用Object或边界类型替换。这导致几个限制:不能直接创建泛型实例,不能使用instanceof,泛型数组与协变冲突,以及在静态上下文中的限制。通配符如<?>用于增强灵活性,<? extends T>只读,<? super T>只写。面试题涉及泛型原理和擦除机制。
43 3
Android面试题之Java 泛型和Kotlin泛型
|
5月前
|
前端开发 API Android开发
Android自定义View之Canvas一文搞定
这篇文章介绍了Android自定义View中如何使用Canvas和Paint来绘制图形。Canvas可理解为画布,用于绘制各种形状如文字、点、线、矩形、圆角矩形、圆和弧。常见API包括`drawText()`、`drawPoint()`、`drawLine()`、`drawRect()`等。文章还提到了Canvas的保存、恢复、平移和旋转方法,通过绘制钟表盘的例子展示了如何实际应用。总结关键点:Canvas与Paint结合用于图像绘制,掌握Canvas的基本绘图函数及坐标变换操作是自定义View的关键。
89 0
Android自定义View之Canvas一文搞定
|
6月前
|
存储 Java 数据库连接
Android Java开发异步
【6月更文挑战第15天】