Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArrayList<Enum> nav args crashing #592

Closed
stanleyguevara opened this issue Mar 5, 2024 · 6 comments
Closed

ArrayList<Enum> nav args crashing #592

stanleyguevara opened this issue Mar 5, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@stanleyguevara
Copy link

stanleyguevara commented Mar 5, 2024

Hello, first of all thanks for this lib, it really makes underlying jetpack library way less of a PITA :)

I think I've found a bug, it might be on base library though.
Either way docs would need an update, as those say:

Type of arguments that will be considered navigation arguments:
- ...
- Enums
- ...
- Array and ArrayList of the above types

So it seems like ArrayList<Enum> should work too, meanwhile:

enum class Step {
    FIRST,
    SECOND
}

data class FailureNavArgs(
    val arrayList: ArrayList<Step>,
)

data class SuccessNavArgs(
    val array: Array<Step>,
)

@RootNavGraph(start = true)
@Destination
@Composable
fun InitialScreen(
    navigator: DestinationsNavigator,
) {
    Column {
        Button(onClick = {
            val failureArgs = FailureNavArgs(arrayListOf(Step.FIRST, Step.SECOND))
            navigator.navigate(FailureScreenDestination(failureArgs))
        }) {
            Text(text = "Failure case")
        }
        Button(onClick = {
            val successArgs = SuccessNavArgs(arrayOf(Step.FIRST, Step.SECOND))
            navigator.navigate(SuccessScreenDestination(successArgs))
        }) {
            Text(text = "Success case")
        }
    }
}

@Destination(navArgsDelegate = FailureNavArgs::class)
@Composable
fun FailureScreen(
    navArgs: FailureNavArgs,
) {
    Text(text = "This will never be shown, args: $navArgs")
}

@Destination(navArgsDelegate = SuccessNavArgs::class)
@Composable
fun SuccessScreen(
    navArgs: SuccessNavArgs,
) {
    Text(text = "This is working OK, args: $navArgs")
}

The crash is:

java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/failure_screen/FIRST,SECOND } cannot be found in the navigation graph ComposeNavGraph(0x78dcd1ef) route=root startDestination={Destination(0x5e379694) route=initial_screen}

This happens on 1.10.1 as well as 1.9.63 as far as I've checked. I can share full repo if needed, but it should be pretty easy to replicate, just copy&paste the above, it's pretty much all there is to it.

@raamcosta
Copy link
Owner

Hi @stanleyguevara !

I have no idea how this was like this for so long, thank you so much for taking the time to report 🙇
Indeed there's an issue specifically with ArrayList.

I will fix it and release a new version, today still. In the meantime, as you found, Array work fine until that is done!

@raamcosta raamcosta added the bug Something isn't working label Mar 5, 2024
@raamcosta
Copy link
Owner

@stanleyguevara please try 1.10.2. Thank you again so much for reporting this! 👍

@ehammo
Copy link

ehammo commented Mar 11, 2024

Hey @raamcosta just to let you know there is still a problem in 1.10.2 when passing an ArrayList and the list is empty.
When the list is empty I get this crash:

java.lang.StringIndexOutOfBoundsException: String index out of range: -2
at java.lang.String.substring(String.java:2064)
at java.lang.String.subSequence(String.java:2107)
at com.ramcosta.composedestinations.navargs.primitives.arraylist.DestinationsEnumArrayListNavType.parseValue(DestinationsEnumArrayListNavType.kt:31

Not sure why. My current solution is to make it nullable, and pass null when empty.

@raamcosta
Copy link
Owner

Hi @ehammo

I cannot reproduce this on my machine. Can you tell me more about the nav arguments of this destination? Is it the only nav arg?
It would also be nice if you could go into DestinationsNavController.navigate method and place a breakpoint in there and tell me how the route parameter looks like.

Thank you!

@ehammo
Copy link

ehammo commented Mar 11, 2024

This is how the code looks like:

data class MyCustomNavArg(
val optionalString: String? = null,
val listOfEnum: ArrayList = ArrayList(),
) : Parcelable

data class AnotherDataClass(
val optionalString: String? = null,
val listOfEnum: List = listOf(),
) : Parcelable

@destination(navArgsDelegate = MyCustomNavArg::class)
@composable
fun MyCustomDestination(...

@destination
@composable
fun AnotherDestination(
navigator: DestinationsNavigator,
) {
data: AnotherDataClass = AnotherDataClass(optionalString = "String")
navigator.navigate(
MyCustomDestination(
optionalString = data.optionalString,
listOfEnum = ArrayList(data.list)
)
)
}

Route looks like this:
"my_custom_destination?optionalString=String&listOfEnum="

@raamcosta
Copy link
Owner

raamcosta commented Mar 11, 2024

I still can't reproduce it.

Here is the exact code I'm using.

@Parcelize
data class MyCustomNavArg(
    val optionalString: String? = null,
    val listOfEnum: ArrayList<Stuff> = ArrayList(),
) : Parcelable

@Parcelize
data class AnotherDataClass(
    val optionalString: String? = null,
    val listOfEnum: List<Stuff> = listOf(),
) : Parcelable

@Destination(navArgsDelegate = MyCustomNavArg::class)
@Composable
fun MyCustom(navArgs: MyCustomNavArg) {
    Text(navArgs.toString())
}

@Destination
@Composable
fun Another(
    navigator: DestinationsNavigator,
) {
    val data = remember { AnotherDataClass(optionalString = "String") }
    LaunchedEffect(data) {
        delay(500)
        navigator.navigate(
            MyCustomDestination(
                optionalString = data.optionalString,
                listOfEnum = ArrayList(data.listOfEnum)
            )
        )
    }
}

The route is my_custom?optionalString=String&listOfEnum=[]. I am navigating to the "AnotherDestination" which then automatically navigates to "MyCustomDestination" after 500ms.

Stuff is a enum class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants