- 关键信息:
画布:尝试使用回收的位图android.graphics.Bitmap@eff9b3e
- 具体日志:
Fatal Exception: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@eff9b3e at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:77) at android.graphics.RecordingCanvas.throwIfCannotDraw(RecordingCanvas.java:278) at android.graphics.BaseRecordingCanvas.drawBitmap(BaseRecordingCanvas.java:91) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:548) at android.view.View.getDrawableRenderNode(View.java:24265) at android.view.View.drawBackground(View.java:24170) at android.view.View.draw(View.java:23893) at android.view.View.updateDisplayListIfDirty(View.java:22776) at android.view.View.draw(View.java:23631)
- 描述
该问题的本质原因就是关键信息中所说的:尝试使用一个已经被回收的bitmap
- 分析
看注释描述,能提取的有用信息是,创建的bitmap可能是同一个对象。看下面的代码,更能说明次问题。
/** * Returns an immutable bitmap from subset of the source bitmap, * transformed by the optional matrix. The new bitmap may be the * same object as source, or a copy may have been made. It is * initialized with the same density as the original bitmap. * * If the source bitmap is immutable and the requested subset is the * same as the source bitmap itself, then the source bitmap is * returned and no new bitmap is created. */ public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) { //... // check if we can just return our argument unchanged if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() && height == source.getHeight() && (m == null || m.isIdentity())) { return source; } //... return bitmap; }
- 结果
当满足上述的两个条件之后,创建了同一个bitmap, 在调用createBitmap之后 直接调用recycle(), 那后续操作的时候肯定会出问题
- 重点场景
recyclerView 列表中,存在大量复用图片,该问题会更加明显
我代码中的一个场景
fun rotateBitmap(bitmap: Bitmap, rotation: Int): Bitmap? { if (rotation == 0) return bitmap val matrix = Matrix() matrix.setRotate(rotation.toFloat()) try { val bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) bitmap.recycle() return bmRotated } catch (e: OutOfMemoryError) { e.printStackTrace() return null } }
当两次调用的bitmap 相同时,我们第一次进行createBitmap, 然后将原bitmap 销毁了,此时刚好bitmap满足上述条件,那将会爆发此问题。
- 处理方法
fun rotateBitmap(bitmap: Bitmap, rotation: Int): Bitmap? { if (rotation == 0) return bitmap val matrix = Matrix() matrix.setRotate(rotation.toFloat()) try { val bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) if (bitmap != bmRotated) { //判断两个bitmap 不相同时进行释放 bitmap.recycle() } return bmRotated } catch (e: OutOfMemoryError) { e.printStackTrace() return null } }
总结
在使用Bitmap 相关时一定要仔细,它是一个直接关系内存,关系应用是否会卡顿的指标,其次,应用目前对于位图的使用可谓是重中之重,哪一个APP没有图片,真的是丝毫不敢出错啊
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)