raamcosta / compose-destinations

Annotation processing library for type-safe Jetpack Compose navigation with no boilerplate.
https://composedestinations.rafaelcosta.xyz
Apache License 2.0
3.14k stars 129 forks source link

Standalone Sealed Classes as NavArgs in Android #655

Open rodrirepresa opened 2 weeks ago

rodrirepresa commented 2 weeks ago

Issue Description: I am confused about the inability to use standalone sealed classes as navigation arguments (NavArgs) in our Destinations. However, I noticed that using data classes that hold sealed classes is allowed. This seems to be related to an issue with Kotlin Symbol Processing (KSP) when generating code.

Not allowed:

public sealed class MyArgument : Parcelable {

    @Parcelize
    public data class Type1(
        val text: String,
    ) : MyArgument()

    @Parcelize
    public data class Type2(
        val text: String,
    ) : MyArgument()
}

Allowed:

public data class MyArgument(
    val argumentType: ArgumentType,
)

public sealed class ArgumentType : Parcelable {

    @Parcelize
    public data class Type1(
        val text: String,
    ) : ArgumentType()

    @Parcelize
    public data class Type2(
        val text: String,
    ) : ArgumentType()
}

In my screen:

@Destination<Graph>(
    start = true,
    style = DestinationStyle.Dialog::class,
    navArgs = MyArgument::class,
)
@Composable
internal fun MyScreen()
raamcosta commented 2 weeks ago

When setting the navArgs in the destination annotation, the class is not the navigation argument, it’s just a class where navigation arguments are defined. So it doesn’t make sense for such a class to be a sealed type: you need a predefined set of arguments, you can’t tell the official nav lib “my arguments can either be these or these other”.

Im on the phone sorry for not formatting the reply, hopefully it’s understandable.

I’ve seen this confusion lately. Maybe I’ll enforce these classes to be named always SomehtingNavArgs to make it clear the args are its fields not itself.

raamcosta commented 2 weeks ago

Another thing: the class passed to Destination annotation navArgs does not need to be itself Parcelable or any other valid navigation type, precisely because it will not be serialised. Instead its fields will.