Closed
Description
Here my RootComponent class
class RootComponent(componentContext: ComponentContext) : ComponentContext by componentContext {
private val navigation = StackNavigation<Configuration>()
val childStack = childStack(
key = "mainRoot",
source = navigation,
serializer = Configuration.serializer(),
initialConfiguration = Configuration.SplashActivity,
handleBackButton = true,
childFactory = ::createRootChild
)
private fun createRootChild(
configuration: Configuration, context: ComponentContext
): Child {
return when (configuration) {
is Configuration.SplashActivity -> Child.SplashActivity(
SplashComponent(contextComponent = context, onTimerComplete = {
navigation.pushNew(Configuration.LoginActivity)
})
)
is Configuration.LoginActivity -> Child.LoginActivity(
LoginComponent(componentContext = context, onLogin = {
navigation.pushNew(Configuration.DashboardActivity)
})
)
is Configuration.DashboardActivity -> Child.DashboardActivity(DashboardComponent(context))
}
}
sealed class Child {
data class SplashActivity(val component: SplashComponent) : Child()
data class LoginActivity(val component: LoginComponent) : Child()
data class DashboardActivity(val component: DashboardComponent) : Child()
}
@Serializable
sealed class Configuration {
@Serializable
data object SplashActivity : Configuration()
@Serializable
data object LoginActivity : Configuration()
@Serializable
data object DashboardActivity : Configuration()
}
}
Here my DashBoardRootComponent class
class DashBoardRootComponent(componentContext: ComponentContext) :
ComponentContext by componentContext {
private val navigation = StackNavigation<Configuration>()
val childStack = childStack(
key = "dashBoardRoot",
source = navigation,
serializer = Configuration.serializer(),
initialConfiguration = Configuration.PlayListActivity,
handleBackButton = true,
childFactory = ::createDashBoardChild
)
private fun createDashBoardChild(
configuration: Configuration, context: ComponentContext
): Child {
return when (configuration) {
is Configuration.PlayListActivity -> Child.PlayListActivity(
PlayListComponent(componentContext = context, onPlayListClick = {
navigation.pushNew(Configuration.TrackListActivity)
})
)
is Configuration.TrackListActivity -> Child.TrackListActivity(TrackListComponent(componentContext = context,
onTrackListClick = {
},
onBackPress = {
navigation.pop()
}))
}
}
sealed class Child {
data class PlayListActivity(val component: PlayListComponent) : Child()
data class TrackListActivity(val component: TrackListComponent) : Child()
// data class DashboardActivity(val component: DashboardComponent) : Child()
}
@kotlinx.serialization.Serializable
sealed class Configuration {
@kotlinx.serialization.Serializable
data object PlayListActivity : Configuration()
@kotlinx.serialization.Serializable
data object TrackListActivity : Configuration()
}
}
My App Component
@Composable
@Preview
fun App(root: RootComponent, dashBoardRoot: DashBoardRootComponent) {
MaterialTheme {
val childStack by root.childStack.subscribeAsState()
Children(
stack = childStack,
animation = stackAnimation(slide()),
content = { child ->
when (val instance = child.instance) {
is RootComponent.Child.SplashActivity -> Splash(instance.component)
is RootComponent.Child.LoginActivity -> Login(instance.component)
is RootComponent.Child.DashboardActivity -> Dashboard(
instance.component,
dashBoardRootComponent = dashBoardRoot
)
}
}
)
}
}
For Android MainActivity 1st Try
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val rootF = retainedComponent {
RootComponent(it)
}
val dashF = retainedComponent {
DashBoardRootComponent(it)
}
setContent {
App(rootF, dashF)
}
}
}
Logcat :
FATAL EXCEPTION: main
Process: com.neonmusic.app, PID: 3633
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.neonmusic.app/com.neonmusic.app.MainActivity}: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3635)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.kt:110)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.StateKeeper(AndroidExt.kt:31)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.stateKeeper(AndroidExt.kt:54)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent(RetainedComponent.kt:101)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent(RetainedComponent.kt:52)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent$default(RetainedComponent.kt:45)
at com.neonmusic.app.MainActivity.onCreate(MainActivity.kt:20)
at android.app.Activity.performCreate(Activity.java:8051)
at android.app.Activity.performCreate(Activity.java:8031)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3608)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
For Android MainActivity 2nd Try from chatGpt reference
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val root = retainedComponentWithKey(key = "RootComponent_mainRoot") {
RootComponent(it)
}
val dashBoardRoot = retainedComponentWithKey(key = "DashBoardRootComponent_dashBoardRoot") {
DashBoardRootComponent(it)
}
setContent {
App(root.first, dashBoardRoot.first)
}
}
private fun <T : Any> retainedComponentWithKey(
key: String,
factory: (ComponentContext) -> T
): Pair<T, String> {
val component = retainedComponent(key = key, handleBackButton = true, factory = factory)
return component to key
}
}
Logcat :
FATAL EXCEPTION: main
Process: com.neonmusic.app, PID: 3248
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.neonmusic.app/com.neonmusic.app.MainActivity}: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3635)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.kt:110)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.StateKeeper(AndroidExt.kt:31)
at com.arkivanov.essenty.statekeeper.AndroidExtKt.stateKeeper(AndroidExt.kt:54)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent(RetainedComponent.kt:101)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent(RetainedComponent.kt:52)
at com.arkivanov.decompose.RetainedComponentKt.retainedComponent$default(RetainedComponent.kt:45)
at com.neonmusic.app.MainActivity.retainedComponentWithKey(MainActivity.kt:33)
at com.neonmusic.app.MainActivity.onCreate(MainActivity.kt:20)
at android.app.Activity.performCreate(Activity.java:8051)
at android.app.Activity.performCreate(Activity.java:8031)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3608)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I am facing this issue only for android
Do code for desktop also but it will working fine.
Here Desktop entry point
fun main() = application {
Window(
onCloseRequest = ::exitApplication,
title = "neon-music-kmp",
) {
val root = remember { RootComponent(DefaultComponentContext(LifecycleRegistry())) }
val dashBoardRoot = remember { DashBoardRootComponent(DefaultComponentContext(LifecycleRegistry())) }
App(root, dashBoardRoot)
}
}
Can any one explain me where i need to give unique key for android retainedComponent ?
Tell me if i am wrong in anything.