Closed matthewbahr-clear closed 1 week ago
This looks a lot like the compose compiler isn't run in the module that SlideInOutNavDecoration
is getting moved to 🤔
That could explain it!
The module that the decoration is moved into has all the standard circuit dependencies:
// Add circuit dependencies
implementation libs.circuit.foundation
implementation libs.circuit.overlay
implementation libs.circuitx.overlays
implementation libs.circuitx.effects
api libs.circuit.codegen.annotations
ksp libs.circuit.codegen.core
testImplementation libs.circuit.test
Does it need to also have androidx.compose.foundation
to work? Or androidx.compose.ui
?
It'll also need the compose gradle plugin applied, then the overridden @Composable
function will get fully generated 🎉
Yep that was it. Missed the compose gradle plugin application!
Thanks!
Circuit Version 0.24.0
Bit of a strange one here but I've encountered a hard crash when attempting to modularize a NavDecoration into a separate package from the UI layer that is implementing it. I have a core utility package that is used by any circuit UI module that has standard utilities for the UI. We just added in a standard NavDecorator based on the default that does a slide in/out transition.
The weirdness happens when you take the NavDecorator out of the same module as the NavigableCircuitContent where it is used. If you do so you'll end up with a abstract method crash at runtime when the NavigableCircuitContent is first invoked.
java.lang.AbstractMethodError: abstract method "void com.slack.circuit.backstack.NavDecoration.DecoratedContent(kotlinx.collections.immutable.ImmutableList, int, androidx.compose.ui.Modifier, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer, int)"
Workarounds I've tried (mostly desperate flailing):
So far nothing works: It will always fail unless I've moved it into the same module as the view, meaning that I can never reuse the code elsewhere.
TLDR:
If the Decorator is in a different module the application will crash at runtime when the NavigableCircuitContent is first invoked.
If the Decorator is in the same module (even if it's a different package in the same module) it works fine.
Stacktrace:
Full stack trace of AbstractMethodError
``` java.lang.AbstractMethodError: abstract method "void com.slack.circuit.backstack.NavDecoration.DecoratedContent(kotlinx.collections.immutable.ImmutableList, int, androidx.compose.ui.Modifier, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer, int)" at com.slack.circuit.foundation.NavigableCircuitContentKt$NavigableCircuitContent$2.invoke(NavigableCircuitContent.kt:110) at com.slack.circuit.foundation.NavigableCircuitContentKt$NavigableCircuitContent$2.invoke(NavigableCircuitContent.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248) at com.slack.circuit.foundation.NavigableCircuitContentKt.NavigableCircuitContent(NavigableCircuitContent.kt:109) at (Fragment wrapping the view) at (Fragment wrapping the view) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at com.slack.circuit.foundation.CircuitCompositionLocalsKt$CircuitCompositionLocals$1.invoke(CircuitCompositionLocals.kt:31) at com.slack.circuit.foundation.CircuitCompositionLocalsKt$CircuitCompositionLocals$1.invoke(CircuitCompositionLocals.kt:30) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at com.slack.circuit.foundation.CircuitCompositionLocalsKt.CircuitCompositionLocals(CircuitCompositionLocals.kt:27) at (Fragment wrapping the view) at (Fragment wrapping the view)$onViewCreated$1$1.invoke((Fragment wrapping the view)) at (Fragment wrapping the view)$onViewCreated$1$1.invoke((Fragment wrapping the view)) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:428) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252) at androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:186) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110) 14:48:33.433 E at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:139) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:138) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:248) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:138) at androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:123) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:90) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3302) at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3235) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:725) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1071) at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:633) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:619) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:123) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1289) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:114) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:164) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.jvm.kt:320) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.jvm.kt:198) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:121) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:114) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1364) at android.view.View.dispatchAttachedToWindow(View.java:23244) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3722) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3729) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3958) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3345) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:11437) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1690) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1699) at android.view.Choreographer.doCallbacks(Choreographer.java:1154) at android.view.Choreographer.doFrame(Choreographer.java:1080) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1647) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:9063) 14:48:33.433 E at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) ```Problematic Code
Full code of the Decoration that works only inside the same module
Exact code of the Slider here: (Duplicate of `DefaultDecoration.kt` with the 10% increased to 100% and the fade removed) ```kt object SlideInOutNavDecoration : NavDecoration { private val FastOutExtraSlowInEasing = CubicBezierEasing(0.208333f, 0.82f, 0.25f, 1f) private const val NORMAL_DURATION = 450 private val forward: ContentTransform by lazy { computeTransition(1) } private val backward: ContentTransform by lazy { computeTransition(-1) } private fun computeTransition(sign: Int): ContentTransform { val enterTransition = slideInHorizontally( initialOffsetX = { fullWidth -> fullWidth * sign }, animationSpec = tween(durationMillis = NORMAL_DURATION, easing = FastOutExtraSlowInEasing), ) + expandHorizontally( animationSpec = tween(durationMillis = NORMAL_DURATION, easing = FastOutExtraSlowInEasing), initialWidth = { (it * .9f).toInt() }, expandFrom = if (sign > 0) Alignment.Start else Alignment.End, ) val exitTransition = slideOutHorizontally( targetOffsetX = { fullWidth -> fullWidth * -sign }, animationSpec = tween(durationMillis = NORMAL_DURATION, easing = FastOutExtraSlowInEasing), ) + shrinkHorizontally( animationSpec = tween(durationMillis = NORMAL_DURATION, easing = FastOutExtraSlowInEasing), targetWidth = { (it * .9f).toInt() }, shrinkTowards = Alignment.End, ) return enterTransition togetherWith exitTransition } @Composable override fun