glide icon indicating copy to clipboard operation
glide copied to clipboard

Compose crash

Open Caij opened this issue 2 years ago • 8 comments
trafficstars

  • version beta01

crash on HorizontalPager change page

fun PlayPageContain(
    rememberHorizontalPagerState: PagerState
) {
    HorizontalPager(state = rememberHorizontalPagerState) { page: Int ->
        if (page == 1) {
            PlayerPage(rememberHorizontalPagerState)
        } else if (page == 0) {
            SimplePlayingQueuePage(rememberHorizontalPagerState)
        } else {
            SimpleCurrentLyricsDetailPage(rememberHorizontalPagerState)
        }
    }
}

@Composable
fun PlayerPage(
    rememberPagerState: PagerState
) {
    val playerComponent by remember { mutableStateOf(PlayerComponent()) }
    val song by playerComponent.model.subscribeAsState()
    Column(modifier = Modifier.fillMaxSize()) {
        val painter = painterResource(MR.images.default_audio_art)
        Box {
            GlideImage(song, modifier = Modifier.padding(top = getSafeTop()).padding(16.dp)
                .fillMaxWidth().aspectRatio(1f).clip(Colors.songRoundedCornerShape),
                contentDescription = null, placeholderPaint = painter)

            val isBuffing by playerComponent.isBuffing.subscribeAsState()
            if (isBuffing) {
                CircularProgressIndicator(modifier = Modifier.width(36.dp).height(36.dp).align(
                    Alignment.Center
                ))
            }
        }

        PlayerControlWidget(playerComponent, song, Modifier.weight(1f), rememberPagerState)

        BottomMenu(playerComponent, rememberPagerState)
    }

    DisposableEffect(playerComponent) {
        playerComponent.uiRun()
        onDispose {
            playerComponent.uiDispose()
        }
    }
}

image

java.lang.IllegalArgumentException: at com.bumptech.glide.util.Preconditions.checkArgument(Preconditions.java:21) at com.bumptech.glide.util.Preconditions.checkArgument(Preconditions.java:16) at com.bumptech.glide.integration.compose.GlideNode$launchRequest$1.invoke(GlideModifier.kt:404) at com.bumptech.glide.integration.compose.GlideNode$launchRequest$1.invoke(GlideModifier.kt:400) at androidx.compose.ui.platform.AndroidComposeView.onEndApplyChanges(AndroidComposeView.android.kt:694) at androidx.compose.ui.node.UiApplier.onEndChanges(UiApplier.android.kt:48) at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:822) at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:849) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1041) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4007) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4007) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:4007) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:721) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:694) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:685) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:669) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:1014) at androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScopeImpl.measure-0kLqBqw(LazyLayoutMeasureScope.kt:121) at androidx.compose.foundation.pager.PagerMeasureKt.getAndMeasure-SGf7dI0(PagerMeasure.kt:476) at androidx.compose.foundation.pager.PagerMeasureKt.measurePager-ntgEbfI(PagerMeasure.kt:141) at androidx.compose.foundation.pager.PagerMeasurePolicyKt$rememberPagerMeasurePolicy$1$1.invoke-0kLqBqw(PagerMeasurePolicy.kt:159) at androidx.compose.foundation.pager.PagerMeasurePolicyKt$rememberPagerMeasurePolicy$1$1.invoke(PagerMeasurePolicy.kt:66) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke-0kLqBqw(LazyLayout.kt:87) at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke(LazyLayout.kt:80) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:866) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126) at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2.invoke-3p2s80s(AndroidOverscroll.kt:578) at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$2.invoke(AndroidOverscroll.kt:577) at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:291) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116) at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1.invoke-3p2s80s(AndroidOverscroll.kt:562) at androidx.compose.foundation.AndroidOverscrollKt$StretchOverscrollNonClippingLayer$1.invoke(AndroidOverscroll.kt:561) at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:291) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116) 2023-10-09 21:00:50.984 32541-32541 AndroidRuntime com.caij.puremusic E at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1499) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasure$2.invoke(LayoutNodeLayoutDelegate.kt:1495) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2299) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:467) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:230) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1495) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:35) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:560) at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.kt:1140) at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:321) at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout-0kLqBqw(MeasureAndLayoutDelegate.kt:389) at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout-0kLqBqw(AndroidComposeView.android.kt:890) at androidx.compose.ui.node.LayoutNode.forceRemeasure(LayoutNode.kt:1214) at androidx.compose.foundation.pager.PagerState.performScroll(PagerState.kt:555) at androidx.compose.foundation.pager.PagerState.access$performScroll(PagerState.kt:165) at androidx.compose.foundation.pager.PagerState$scrollableState$1.invoke(PagerState.kt:203) at androidx.compose.foundation.pager.PagerState$scrollableState$1.invoke(PagerState.kt:203) at androidx.compose.foundation.gestures.DefaultScrollableState$scrollScope$1.scrollBy(ScrollableState.kt:166) at androidx.compose.foundation.gestures.ScrollingLogic$dispatchScroll$performScroll$1.invoke-MK-Hz9U(Scrollable.kt:425) at androidx.compose.foundation.gestures.ScrollingLogic$dispatchScroll$performScroll$1.invoke(Scrollable.kt:417) at androidx.compose.foundation.AndroidEdgeEffectOverscrollEffect.applyToScroll-Rhakbz0(AndroidOverscroll.kt:180) at androidx.compose.foundation.gestures.ScrollingLogic.dispatchScroll-3eAAhYA(Scrollable.kt:438) at androidx.compose.foundation.gestures.ScrollDraggableState.dragBy(Scrollable.kt:526) at androidx.compose.foundation.gestures.DraggableNode$pointerInputNode$1$1$1$1.invokeSuspend(Draggable.kt:311) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81) at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41) at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1449) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1459) at android.view.Choreographer.doCallbacks(Choreographer.java:1089) at android.view.Choreographer.doFrame(Choreographer.java:998) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1431) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:210) at android.os.Looper.loop(Looper.java:299) at android.app.ActivityThread.main(ActivityThread.java:8261) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:559)

Caij avatar Oct 09 '23 13:10 Caij

I've tried this on an emulator and I'm not able to reproduce this crash:

  val pagerState = rememberPagerState(pageCount = {
      10
    })
    HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize(1f)) { page: Int ->
      Column(modifier = Modifier.fillMaxSize(1f)) {
        Box {
          val model = if (page == 0) {
            R.drawable.star_big_on
          } else if (page == 1) {
            R.drawable.star_big_off
          } else if (page == 5) {
            R.drawable.btn_radio
          } else if (page == 6) {
            R.drawable.arrow_down_float
          } else {
            R.drawable.button_onoff_indicator_on
          }
          GlideImage(model = model, contentDescription = "", modifier = Modifier.width(100.dp).height(100.dp))
        }
      }
    }

Can you think of any tweak I should make to that code to reproduce the issue?

For now I have a speculative fix - I think nothing stops the sideEffect block from being scheduled multiple times, so that assertion should instead be an early return. It would be nice to validate that works though (and maybe add a test).

sjudd avatar Oct 17 '23 04:10 sjudd

@sjudd the placeholder causes the crash, that's why you don't see it in your example.

You can find here example code reproducing the issue.

ktiniatros avatar Oct 20 '23 13:10 ktiniatros

I am currently seeing this in my app in prod. Hopefully it gets fixed soon! Thanks!

cameronhenige avatar Nov 06 '23 17:11 cameronhenige

@sjudd hello , when do you plan to merge?

Caij avatar Nov 23 '23 11:11 Caij

I am also encountering this crash issue with same stack trace (IllegalArgumentException), using LazyColumn with GlideImage, and setting a placeholder using Painter to either loading or failure Also, need to set the LazyColumn's height to be small enough to be able to scroll through the items. The moment I scroll it crashes.

Some scenarios:

  • If I don't set loading nor failure, no crash when scrolling
  • If I set loading or failure to placeholder(ColorDrawable(0xff0000FF.toInt())), no crash when scrolling
  • If I set loading or falure to placeholder(R.drawable.ic_avatar_placeholder), no crash when scrolling
  • If I set loading or failure to placeholder(painterResource(R.drawable.ic_avatar_placeholder)), it crashes when scrolling

Somehow, it doesn't like it when using Painter as placeholder.

I need to use Painter as placeholder because I created a custom Painter to draw user's initials, if their profile photo failed to load. So if user Robert Fox's avatar failed to load, the avatar will show 'RF' instead as a fallback. So I can't use static drawable resource.

iori57 avatar Jan 10 '24 10:01 iori57

I'm facing the same issue with a LazyColumn, in my case it takes a few seconds of scrolling to see the crash. Removing the painterResource and passing the resource ID directly as @iori57 suggested fixes it.

jorgedotcom avatar Mar 08 '24 14:03 jorgedotcom

@sjudd I hit this problem much like @jorgedotcom and @iori57 using a vectorPainter for the failure placeholder. I also hit the issue only while scrolling my LazyColumn. Like them my initial workaround was to disable the use of the painter which seemed to fix the issue although it seemed like a hack.

I searched issues and found this ticket and saw that you made a fix. I tried the latest beta2 snapshot build of glide compose with my original code utilizing the vectorPainter. I'm happy to report it fixed the problem and so far everything looks good. I look forward to an official release of compose beta2.

joerogers avatar Apr 24 '24 18:04 joerogers