voyager
voyager copied to clipboard
push Screen Crash with Double BottomSheetNavigator and Transition
version
v1.0.0
example code
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Navigator(StartScreen) { navigator ->
GlobalNavigatorWrapper(navigator) {
SlideTransition(navigator) {
it.Content()
}
}
}
}
}
}
val LocalGlobalNavigator: ProvidableCompositionLocal<Navigator> =
staticCompositionLocalOf { error("LocalGlobalNavigator not initialized") }
@Composable
fun GlobalNavigatorWrapper(navigator: Navigator, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalGlobalNavigator provides navigator, content)
}
object StartScreen : Screen {
private fun readResolve(): Any = StartScreen
@Composable
override fun Content() {
BottomSheetNavigator {
TabNavigator(TestTab) {
CurrentScreen()
}
}
}
}
object TestTab : Tab {
private fun readResolve(): Any = TestTab
override val options: TabOptions
@Composable get() = TabOptions(0U, "test")
@Composable
override fun Content() {
val navigator = LocalGlobalNavigator.current
Column {
Button(onClick = {
navigator.push(JumpScreen)
}) {
Text(text = "jump with BottomSheetNavigator")
}
Button(onClick = {
navigator.push(Jump2Screen)
}) {
Text(text = "jump no BottomSheetNavigator")
}
}
}
}
object JumpScreen : Screen {
private fun readResolve(): Any = JumpScreen
@Composable
override fun Content() {
BottomSheetNavigator {
Text(text = "with BottomSheetNavigator")
}
}
}
object Jump2Screen : Screen {
private fun readResolve(): Any = Jump2Screen
@Composable
override fun Content() {
Text(text = "no BottomSheetNavigator")
}
}
crash log
after clik "jump with BottomSheetNavigator" button will crash:
java.lang.IllegalArgumentException: Key cafe.adriel.voyager.navigator.bottomSheet.HiddenBottomSheetScreen:currentScreen was used multiple times
at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:89)
at androidx.compose.runtime.saveable.SaveableStateHolderImpl$SaveableStateProvider$1$1.invoke(SaveableStateHolder.kt:88)
at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:83)
at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1295)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:984)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1005)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1099)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3599)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:633)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:619)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:500)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:472)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:463)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:447)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:872)
at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke-0kLqBqw(BoxWithConstraints.kt:69)
at androidx.compose.foundation.layout.BoxWithConstraintsKt$BoxWithConstraints$1$1.invoke(BoxWithConstraints.kt:67)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:709)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2303)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:500)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256)
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:1617)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596)
at androidx.compose.animation.AnimatedEnterExitMeasurePolicy.measure-3p2s80s(AnimatedVisibility.kt:851)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.animation.EnterExitTransitionModifierNode.measure-3p2s80s(EnterExitTransition.kt:1156)
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)
avoid crash
- remove BottomSheetNavigator in StartScreen or JumpScreen
- remove Transition
Hi! I happened to have the same issue (just on one bottom sheet and just in release builds, not in debug ones). Do I have to both remove the SlideTransition
and remove the BottomSheetNavigator
altogether?
I don't know if it helps, but in my case I have the BottomSheetNavigator
as parent and the root navigator as a child, the crash happens just when I call show(screen: Screen)
on the former.
EDIT: I realized I am using a third Navigator inside the bottom sheet content, and that is the cause of the issue, this explains why it crashes only with that bottom sheet and not the other plain ones.
Hi! I happened to have the same issue (just on one bottom sheet and just in release builds, not in debug ones). Do I have to both remove the
SlideTransition
and remove theBottomSheetNavigator
altogether?I don't know if it helps, but in my case I have the
BottomSheetNavigator
as parent and the root navigator as a child, the crash happens just when I callshow(screen: Screen)
on the former.EDIT: I realized I am using a third Navigator inside the bottom sheet content, and that is the cause of the issue, this explains why it crashes only with that bottom sheet and not the other plain ones.
Now I use the following code to use BottomSheetNavigator and Transition simultaneously . I hope it will help you.
Navigator(MainScreen) { navigator ->
GlobalNavigatorWrapper(navigator) {
MyBottomSheetNavigator {
ParcelableNavigatorWrapper {
MyCustomTransition(navigator) { screen ->
screen.Content()
}
}
}
}
}
@OptIn(ExperimentalVoyagerApi::class)
@Composable
fun ParcelableNavigatorWrapper(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalNavigatorSaver provides parcelableNavigatorSaver(),
content = content
)
}
val LocalGlobalNavigator: ProvidableCompositionLocal<Navigator> =
staticCompositionLocalOf { error("LocalGlobalNavigator not initialized") }
@Composable
fun GlobalNavigatorWrapper(navigator: Navigator, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalGlobalNavigator provides navigator, content)
}
I am removing the nested navigator inside the bottom sheet, I do not actually need it and can achieve a similar behaviour with Crossfade
to have a transition.