MateriiApps / pullrefresh

Standalone pull to refresh library for Jetpack Compose multiplatform.
MIT License
44 stars 2 forks source link

Crashes when pulling to refresh with the latest compose multiplatform (1.6.x) #10

Closed tom-pratt closed 5 months ago

tom-pratt commented 5 months ago

Im using compose multiplatform 1.6.0-beta01 and get the following crash when trying to pull to refresh. Also before it crashes I see the refresh indicator but its behind the content.

02-06 07:42:46.967 11205 11205 E AndroidRuntime: java.lang.NoSuchMethodError: No virtual method at(Ljava/lang/Object;I)Landroidx/compose/animation/core/KeyframesSpec$KeyframeEntity; in class Landroidx/compose/animation/core/KeyframesSpec$KeyframesSpecConfig; or its super classes (declaration of 'androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig' appears in /data/app/~~faK1FaIXxZhNt8R03vWoRQ==/se-tObbnBJpVs3IJ6fKExgKUA==/base.apk)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.CircularLoadingIndicatorKt$CircularLoadingIndicator$endAngle$2.invoke(CircularLoadingIndicator.kt:104)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.CircularLoadingIndicatorKt$CircularLoadingIndicator$endAngle$2.invoke(CircularLoadingIndicator.kt:102)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.animation.core.AnimationSpecKt.keyframes(AnimationSpec.kt:649)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.CircularLoadingIndicatorKt.CircularLoadingIndicator-LxG7B9w(CircularLoadingIndicator.kt:102)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.PullRefreshIndicatorKt$PullRefreshIndicator$2$1.invoke(PullRefreshIndicator.kt:128)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.PullRefreshIndicatorKt$PullRefreshIndicator$2$1.invoke(PullRefreshIndicator.kt:120)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.animation.CrossfadeKt$Crossfade$5$1.invoke(Crossfade.kt:133)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.animation.CrossfadeKt$Crossfade$5$1.invoke(Crossfade.kt:128)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:142)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:57)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.PullRefreshIndicatorKt.PullRefreshIndicator-Y0xEhic(PullRefreshIndicator.kt:116)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.PullRefreshIndicatorKt$PullRefreshIndicator$3.invoke(Unknown Source:23)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at dev.materii.pullrefresh.PullRefreshIndicatorKt$PullRefreshIndicator$3.invoke(Unknown Source:10)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:192)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2556)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2827)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3314)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3265)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:938)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1155)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:127)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:583)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:551)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.view.Choreographer.doCallbacks(Choreographer.java:899)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.view.Choreographer.doFrame(Choreographer.java:827)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.os.Handler.handleCallback(Handler.java:942)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:99)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.os.Looper.loopOnce(Looper.java:201)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:288)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:7872)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
02-06 07:42:46.967 11205 11205 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
X1nto commented 5 months ago

The issue is with compose multiplatform 1.6.0. There's a dependency mismatch between compose animations 1.6.0 and 1.5.3. The best solution for you is to downgrade to multiplatform 1.5.10. Alternatively, you could wait for pullrefresh to be updated to latest compose.

tom-pratt commented 5 months ago

Thank you very much for the quick reply! I'll wait for the update since im using some new stuff related to resources from 1.6 already.

X1nto commented 5 months ago

@tom-pratt pullrefresh 1.4.0-beta01 released with compose-multiplatform 1.6.0-beta02 support, it should fix the crash. As for the indicator being behind the content, that might be because you're using DragRefreshLayout, try PullRefreshLayout.

tom-pratt commented 5 months ago

Thank you! That fixes the crash. The indicator is still showing up behind though and im definitely using PullRefreshLayout. I thought it might be related to elevation or something but double checked and its not that. Just using it like this.

        val pullRefreshState = rememberPullRefreshState(
            refreshing = calendarViewModel.refreshing.collectAsState().value,
            onRefresh = { calendarViewModel.update() },
        )
        PullRefreshLayout(pullRefreshState) {
            val competitions = calendarViewModel.competitions.collectAsState().value
            LazyColumn {
                items(competitions) { competition ->
                    CompetitionCard(navigator, competition)
                }
            }
        }

pullrefresh_behind.webm

tom-pratt commented 5 months ago

I was able to fix it by moving the content() in the PullRefreshLayout

@Composable
fun PullRefreshLayout2(
    state: PullRefreshState,
    modifier: Modifier = Modifier,
    flipped: Boolean = false,
    enabled: Boolean = true,
    indicator: @Composable () -> Unit = {
        PullRefreshIndicator(
            state = state,
            flipped = flipped
        )
    },
    content: @Composable () -> Unit
) {
    Box(
        modifier = Modifier
            .pullRefresh(
                state = state,
                inverse = flipped,
                enabled = enabled
            )
            .then(modifier)
    ) {
        content()

        val indicatorAlignment = if (flipped) Alignment.BottomCenter else Alignment.TopCenter
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .align(indicatorAlignment),
            contentAlignment = Alignment.Center
        ) {
            indicator()
        }

//        content() // Move to top
    }
}
X1nto commented 5 months ago

Oh, I see. Could you create a Pull Request so that we can properly credit you? No need to create PullRefreshLayout2, just update the existing PullRefreshLayout.

tom-pratt commented 5 months ago

Just made the PR. Thanks for your help and great lib!