skydoves / landscapist

🌻 A pluggable, highly optimized Jetpack Compose and Kotlin Multiplatform image loading library that fetches and displays network images with Glide, Coil, and Fresco.

Home Page:https://skydoves.github.io/landscapist/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Occasional crash

p-lr opened this issue · comments

Please complete the following information:

  • Library Version 2.2.0
  • Affected Device(s) [Pixel 6.0, Pixel 4a, Galaxy S20 FE 5G, Galaxy S21 5G, Galaxy S9, Redmi Note 10 5G, Redmi Note 11, ..] mostly on Android 13

Describe the Bug:

Very similarly to #233, the app sometimes crashes with the stack trace below.
Downgrading to 2.1.12 resolves the issue (2.1.13 has the issue).

Fatal Exception: java.lang.RuntimeException
Canvas: trying to use a recycled bitmap android.graphics.Bitmap@76749a6
android.graphics.BaseCanvas.throwIfCannotDraw (BaseCanvas.java:87)
android.graphics.RecordingCanvas.throwIfCannotDraw (RecordingCanvas.java:263)
android.graphics.BaseRecordingCanvas.drawBitmap (BaseRecordingCanvas.java:98)
androidx.compose.ui.graphics.AndroidCanvas.drawImageRect-HPBpro0 (AndroidCanvas.android.kt:271)
androidx.compose.ui.graphics.drawscope.CanvasDrawScope.drawImage-AZ2fEMs (CanvasDrawScope.kt:263)
androidx.compose.ui.node.LayoutNodeDrawScope.drawImage-AZ2fEMs (LayoutNodeDrawScope.kt:34)
androidx.compose.ui.graphics.drawscope.DrawScope.drawImage-AZ2fEMs$default (DrawScope.kt:510)
androidx.compose.ui.graphics.painter.BitmapPainter.onDraw (BitmapPainter.kt:93)
androidx.compose.ui.graphics.painter.Painter.draw-x_KDEd0 (Painter.kt:212)
androidx.compose.ui.draw.PainterModifierNode.draw (PainterModifier.kt:347)
androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release (LayoutNodeDrawScope.kt:92)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:370)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers (NodeCoordinator.kt)
androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke (NodeCoordinator.kt:396)
androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke (NodeCoordinator.kt:395)
androidx.compose.runtime.snapshots.Snapshot$Companion.observe (Snapshot.kt:2200)
androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke (SnapshotStateObserver.kt:234)
androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke (SnapshotStateObserver.kt:230)
androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations (DerivedState.kt:341)
androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations (SnapshotState.kt)
androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads (SnapshotStateObserver.kt:230)
androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release (OwnerSnapshotObserver.kt:120)
androidx.compose.ui.node.NodeCoordinator.invoke (NodeCoordinator.kt:395)
androidx.compose.ui.node.NodeCoordinator.invoke (NodeCoordinator.kt:58)
androidx.compose.ui.platform.RenderNodeApi29.record (RenderNodeApi29.android.kt:209)
androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList (RenderNodeLayer.android.kt:301)
androidx.compose.ui.platform.RenderNodeLayer.drawLayer (RenderNodeLayer.android.kt:242)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:354)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.node.InnerNodeCoordinator.performDraw (InnerNodeCoordinator.kt:151)
androidx.compose.ui.node.LayoutNodeDrawScope.drawContent (LayoutNodeDrawScope.kt:64)
androidx.compose.material.ripple.AndroidRippleIndicationInstance.drawIndication (Ripple.android.kt:184)
androidx.compose.foundation.IndicationModifier.draw (Indication.kt:183)
androidx.compose.ui.node.BackwardsCompatNode.draw (BackwardsCompatNode.kt:361)
androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release (LayoutNodeDrawScope.kt:92)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:370)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.node.InnerNodeCoordinator.performDraw (InnerNodeCoordinator.kt:151)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.node.InnerNodeCoordinator.performDraw (InnerNodeCoordinator.kt:151)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.node.InnerNodeCoordinator.performDraw (InnerNodeCoordinator.kt:151)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.LayoutNodeDrawScope.drawContent (LayoutNodeDrawScope.kt:64)
androidx.compose.foundation.Background.draw (Background.kt:107)
androidx.compose.ui.node.BackwardsCompatNode.draw (BackwardsCompatNode.kt:361)
androidx.compose.ui.node.LayoutNodeDrawScope.draw-x_KDEd0$ui_release (LayoutNodeDrawScope.kt:92)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:370)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutModifierNodeCoordinator.performDraw (LayoutModifierNodeCoordinator.kt:236)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.access$drawContainedDrawModifiers (NodeCoordinator.kt)
androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke (NodeCoordinator.kt:396)
androidx.compose.ui.node.NodeCoordinator$invoke$1.invoke (NodeCoordinator.kt:395)
androidx.compose.runtime.snapshots.Snapshot$Companion.observe (Snapshot.kt:2200)
androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke (SnapshotStateObserver.kt:234)
androidx.compose.runtime.snapshots.SnapshotStateObserver$observeReads$1$1.invoke (SnapshotStateObserver.kt:230)
androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations (DerivedState.kt:341)
androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations (SnapshotState.kt)
androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads (SnapshotStateObserver.kt:230)
androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release (OwnerSnapshotObserver.kt:120)
androidx.compose.ui.node.NodeCoordinator.invoke (NodeCoordinator.kt:395)
androidx.compose.ui.node.NodeCoordinator.invoke (NodeCoordinator.kt:58)
androidx.compose.ui.platform.RenderNodeApi29.record (RenderNodeApi29.android.kt:209)
androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList (RenderNodeLayer.android.kt:301)
androidx.compose.ui.platform.RenderNodeLayer.drawLayer (RenderNodeLayer.android.kt:242)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:354)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.node.InnerNodeCoordinator.performDraw (InnerNodeCoordinator.kt:151)
androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers (NodeCoordinator.kt:367)
androidx.compose.ui.node.NodeCoordinator.draw (NodeCoordinator.kt:359)
androidx.compose.ui.node.LayoutNode.draw$ui_release (LayoutNode.kt:866)
androidx.compose.ui.platform.AndroidComposeView.dispatchDraw (AndroidComposeView.android.kt:1041)
android.view.View.draw (View.java:24409)
android.view.View.updateDisplayListIfDirty (View.java:23267)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.draw (View.java:24409)
androidx.core.widget.NestedScrollView.draw (NestedScrollView.java:2209)
android.view.View.updateDisplayListIfDirty (View.java:23267)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild (CoordinatorLayout.java:1277)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.draw (View.java:24409)
android.view.View.updateDisplayListIfDirty (View.java:23267)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
androidx.fragment.app.FragmentContainerView.drawChild (FragmentContainerView.kt:235)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
androidx.fragment.app.FragmentContainerView.dispatchDraw (FragmentContainerView.kt:225)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
androidx.fragment.app.FragmentContainerView.drawChild (FragmentContainerView.kt:235)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
androidx.fragment.app.FragmentContainerView.dispatchDraw (FragmentContainerView.kt:225)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
android.view.View.updateDisplayListIfDirty (View.java:23253)
android.view.View.draw (View.java:24136)
android.view.ViewGroup.drawChild (ViewGroup.java:4748)
android.view.ViewGroup.dispatchDraw (ViewGroup.java:4505)
com.android.internal.policy.DecorView.dispatchDraw (DecorView.java:1540)
android.view.View.draw (View.java:24409)
com.android.internal.policy.DecorView.draw (DecorView.java:1513)
android.view.View.updateDisplayListIfDirty (View.java:23267)
android.view.ThreadedRenderer.updateViewTreeDisplayList (ThreadedRenderer.java:777)
android.view.ThreadedRenderer.updateRootDisplayList (ThreadedRenderer.java:783)
android.view.ThreadedRenderer.draw (ThreadedRenderer.java:881)
android.view.ViewRootImpl.draw (ViewRootImpl.java:5647)
android.view.ViewRootImpl.performDraw (ViewRootImpl.java:5330)
android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:4486)
android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:3116)
android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:10885)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:1301)
android.view.Choreographer$CallbackRecord.run (Choreographer.java:1309)
android.view.Choreographer.doCallbacks (Choreographer.java:923)
android.view.Choreographer.doFrame (Choreographer.java:852)
android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1283)
android.os.Handler.handleCallback (Handler.java:942)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loopOnce (Looper.java:226)
android.os.Looper.loop (Looper.java:313)
android.app.ActivityThread.main (ActivityThread.java:8757)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

Expected Behavior:

Don't crash.

Hey @p-lr, do you still face the same issue since version 2.2.3? And I'm wondering which Landscapist library you use. I guess it seems to the Glide.

Hey @skydoves, the application uses Kotlin 1.8.20 and compose BOM 2023.05.01. This is why using Landscapist 2.2.0 seems appropriate.

When using the latest version 2.2.3, I cannot reproduce. However 2.2.3 has Kotlin 1.9.0 as transitive dependency, and we're not ready to fully test the update yet.

2.2.2 works fine too, and is close to our current setup in terms of dependencies. I can also confirm that I can reproduce the issue with 2.2.1
It appears that #303 which introduced a clearTarget parameter (false by default) fixed the issue. It looks like sometimes, Glide.with(context).clear(target) throws the runtime exception on some targets.
Maybe wrap the clear call in a try catch block?

Yes, exactly #303 used to occur the bitmap issues since the very first version. Even if we place them inside a try-catch, the issue still happens because a new item inside a Lazy_ will reuse a recycled bitmap.

Alright, so we won't use clearTarget = true. It's ok for me.
Feel free to close the issue.

Thanks for checking this issue @p-lr! If I find any better solution, I will definitely let you know via this comment.