androidkotlinandroid-jetpack-composeandroid-jetpack-navigationnavigation-compose

Issue with popBackStack and Type Safety in Navigation Compose wit Serialization


I'm working on an Android app using Navigation Compose with type safety. I have the following navigation setup with four screens: ScreenA, ScreenB, ScreenC, and ScreenD. The navigation flow is as follows:

Navigate from ScreenA to ScreenB with an argument. Navigate from ScreenB to ScreenC. Navigate from ScreenC to ScreenD. From ScreenD, I want to pop back to ScreenB.

To achieve this, I call the following function:

navController.popBackStack(ScreenBRoute, inclusive = false)

However, I'm encountering the following error:

kotlinx.serialization.SerializationException: Serializer for class 'Companion' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.

ScreenB route looks like this:

@Serializable
data class ScreenBRoute(val arg: String)

fun NavGraphBuilder.screenB(
    navController: NavController
) {
    composable<ScreenBRoute> { entry ->
        val arg: ScreenBRoute = entry.toRoute()
        ...
       // ScreenB screen component
    }
}

I suspect that the correct approach might be:

navController.popBackStack(ScreenBRoute(), inclusive = false)

However, ScreenBRoute requires an argument that I don't want to provide in this situation. Simply navigating back to ScreenB without passing the argument should be sufficient, but I can't find a way to do this without encountering the error.

The following workaround:

navController.popBackStack(ScreenCRoute, inclusive = true)

isn't a viable solution for my case due to specific requirements.

I use following libraries and plugins:

androidx.navigation:navigation-compose:2.8.0-beta06
org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3
plugin: id 'org.jetbrains.kotlin.plugin.serialization' version '1.7.10'

Solution

  • If you want to pop to the topmost instance of ScreenBRoute, you need to use the other version of popBackStack that takes a KClass:

    navController.popBackStack<ScreenBRoute>(inclusive = false)