glide icon indicating copy to clipboard operation
glide copied to clipboard

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

Open animeshPE91 opened this issue 2 years ago • 6 comments

Hi Glide team,

Recently after app release we started seeing this issue for few users.

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

The glide that we are using is com.github.bumptech.glide:glide:4.11.0

the retrofit library that we are using is com.squareup.retrofit2:retrofit:2.9.0

Following is the code snippet I am using for loading a image using glide into imageView

context?.let { context ->
            Glide.with(context)
                .load(story.url)
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .skipMemoryCache(true)
                .placeholder(binding.ivStory.drawable)
                .listener(object: RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        return false
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        binding.loader.visibility = View.GONE
                        animation.start()
                        return false
                    }
                }
                )
                .into(binding.ivStory)

The error that I am getting on firebase is as follows

Fatal Exception: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@d7a7131
       at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:55)
       at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:234)
       at android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:97)
       at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529)
       at android.widget.ImageView.onDraw(ImageView.java:1376)
       at android.view.View.draw(View.java:19442)
       at android.view.View.updateDisplayListIfDirty(View.java:18392)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1975)
       at android.view.View.draw(View.java:19445)
       at android.view.View.updateDisplayListIfDirty(View.java:18392)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1975)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at androidx.constraintlayout.widget.ConstraintLayout.dispatchDraw(ConstraintLayout.java:1975)
       at android.view.View.draw(View.java:19445)
       at android.view.View.updateDisplayListIfDirty(View.java:18392)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at androidx.drawerlayout.widget.DrawerLayout.drawChild(DrawerLayout.java:1426)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.draw(View.java:19445)
       at android.view.View.updateDisplayListIfDirty(View.java:18392)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.updateDisplayListIfDirty(View.java:18383)
       at android.view.View.draw(View.java:19170)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4324)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4087)
       at android.view.View.draw(View.java:19445)
       at com.android.internal.policy.DecorView.draw(DecorView.java:892)
       at android.view.View.updateDisplayListIfDirty(View.java:18392)
       at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:676)
       at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:682)
       at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:790)
       at android.view.ViewRootImpl.draw(ViewRootImpl.java:3503)
       at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3285)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2782)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1718)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7513)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1066)
       at android.view.Choreographer.doCallbacks(Choreographer.java:878)
       at android.view.Choreographer.doFrame(Choreographer.java:794)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1052)
       at android.os.Handler.handleCallback(Handler.java:790)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:210)
       at android.app.ActivityThread.main(ActivityThread.java:7080)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:523)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:863)

Can you please help me understand what I am doing wrong here; Or if i can replace/improve this code to avoid this issue

animeshPE91 avatar Dec 27 '22 08:12 animeshPE91

Have you solved this problem

DearZack avatar Mar 20 '23 12:03 DearZack

I have a similar problem too, which is occurred after user opening app from background.

  • Glide version: 4.16.0

It's expected to set ImageView's imageDrawable null, if the Bitmap in Drawable the ImageView holds is recycled. But obviously, here the Drawable that ImageView holds is not set null.

I don't know whether system or Glide recycled that Bitmap.

The following is the code:

fun ImageView.setTransformedImageBitmap(
    imageUrl: String?,
    transformation: Transformation<Bitmap>,
    currentUrlFetcher: () -> String?
) {
    Glide.with(this)
        .asBitmap()
        .load(imageUrl)
        .transform(transformation)
        .transform(WebpDrawable::class.java, WebpDrawableTransformation(transformation))
        .transition(BitmapTransitionOptions.withCrossFade())
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .listener(
            object : RequestListener<Bitmap> {
                override fun onLoadFailed(
                    e: GlideException?,
                    model: Any?,
                    target: Target<Bitmap>,
                    isFirstResource: Boolean
                ): Boolean {
                    e?.run {
                        // some error logic
                    }
                    return false
                }

                override fun onResourceReady(
                    resource: Bitmap,
                    model: Any,
                    target: Target<Bitmap>,
                    dataSource: DataSource,
                    isFirstResource: Boolean
                ): Boolean {
                    val currentUrl = currentUrlFetcher()
                    val resourceValid = !resource.isRecycled
                    if (currentUrl != imageUrl) {
                        Log.e(TAG, "Image url are inconsistent!")
                        return true
                    }
                    if (!resourceValid) {
                        Log.e(TAG, "Resource invalid!")
                        return true
                    }
                    return false
                }
            }
        )
        .into(this)
}

Madderate avatar Jan 24 '24 09:01 Madderate

@Madderate were you able to find a fix for this? having a similar issue when a user opens the app from the background as well

davidlam-gc avatar Apr 15 '24 18:04 davidlam-gc