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

Nested Destination NavGraph with default one being the "deeper #578

Closed
lucanicoletti opened this issue Feb 5, 2024 · 4 comments
Closed
Labels
feedback needed Extra attention is needed

Comments

@lucanicoletti
Copy link

lucanicoletti commented Feb 5, 2024

I inherited an Android Project that uses this library, and so far I had no issues.
All navigations were handled correctly and I was able to add several new screens and navigate between them without problems.
Last week I had to add a resultRecipient: ResultRecipient<MyDestination, Boolean>, to one of the screens.
It all worked well, the app was building and the navigation worked with no problems, handling the results.
Fast-forward to the day after, and the app started crashing on the navigation (to the screen where that resultRecipient was added).

The crash is caused by:
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/my_screen/param1/param2 } cannot be found in the navigation graph ComposeNavGraph(0xb4ff03f7) route=show_root startDestination={Destination(0x442b361f) route=home_screen}

Trying to understand how this was possible, I found out the project is using a somewhat weird configuration.
There are 2 NavGraph defined.
One is the above show_root, which holds the screens that are displayed with a BottomBar layout.
Another one is the login, which is used for the login flow (there are two different activities that hold the two graphs).

The MainActivity has a DestinationNavHost that uses the default NavGraph (RootNavGraph).
As follow:

    val engine = rememberAnimatedNavHostEngine()
    val navController = engine.rememberNavController()
    
    DestinationsNavHost(
       navGraph = NavGraphs.root,
       startRoute = startRoute,
       engine = engine,
       navController = navController
    )

the startRoute is defined as follow

@RootNavGraph(start = true) // sets this as the start destination of the default nav graph
@Destination(navArgsDelegate = ShowRootScreenScreenArgs::class, style = RootScreenStyle::class)
@Composable
fun ShowRootScreen(

This screen holds another DestinationsNavHost which defines navGraph = NavGraphs.showRoot, (not the default one, a custom-made one).
Inside this inner DestinationsNavHost the screens marked with the ShowRootNavGraph are added with the composable(Destination) { Screen() } function.

A few of those screens are lists of items, which then navigate the user to the detail page of such items, which is not marked as ShowRootNavGraph, and so is using the default RootNavGraph, which started to crash, apparently at random.
I updated the library version (which wasn't the latest released) - currently on 1.9.63 - and this solved the crash after a clean and rebuild of the project.

Fast forward another few days (weekend in between), and without changing anything in the project, simply re-running the app, it now crashes again with the same stack trace.
I realise there is a problem in the graphs, but I couldn't figure out what is been done wrong, and how I could possibly fix it.
I tried removing the resultRecipient as it was the only thing changed on the screen/destination, but that didn't solve the thing.

@lucanicoletti
Copy link
Author

I've read this comment and I just double-checked.
My ShowRootScreen is a destination, but the call to DestinationNavHost inside of it uses another NavGraph

DestinationsNavHost(
        navGraph = NavGraphs.showRoot,
        [...],
)

@raamcosta
Copy link
Owner

Hi @lucanicoletti , I'm sorry it took me so long to get back to you. I hope you found a workaround in the mean time 🙏

Let me start by making something clear:

Inside this inner DestinationsNavHost the screens marked with the ShowRootNavGraph are added with the composable(Destination) { Screen() } function.

This is not adding screens. Differently from official compose navigation library, the screens are added when you pass one NavGraph to the DestinationsNavHost, since that nav graph has information needed to add all its nested graphs and destinations.
This is just overriding the common way the library calls the annotated Composables, by manually calling them. Usually useful when you want to pass some compose state from the NavHost level down to the screen level.

Besides this, it's really hard for me to understand exactly what's happening, but it does sound like a complicated setup, probably unwarranted.
The "show root" nav graph, passed to the inner DestinationsNavHost, means that all screens of that nav host, can only navigate to other screens of that graph. So, if you're trying to navigate to a screen registered to the outer "root" graph, that would require using a NavController from that graph, otherwise the crash you're experience is to be expected (I can't answer to the seemingly random factor, if it is indeed there, it will be caused by official library that we use to navigate, not caused by Compose Destinations).

Maybe you can show me the contents of your NavGraphs generated object.

Let me know if this helps!

@raamcosta raamcosta added the feedback needed Extra attention is needed label Mar 11, 2024
@lucanicoletti
Copy link
Author

No worries for the late reply. As you've guessed, I found a "solution". I would like to contribute more, but I'm unsure with what I can share.
The "solution" was to inline a function.
The "outer" DestinationNavHost in the MainActivity was navigating the ShowRootSceen, and that screen had a Scaffold, which called a function MyNavHost which inside used the second and inner DestinationNavHost.
I don't know why, but moving the code from MyNavHost inline inside the Scaffold of the ShowRootScreen removed the problem.
Perhaps without having the composable(destination) { MyScreen } directly inside of it, the navHost wasn't able to recognise the graph and its routes/destinations?

@raamcosta
Copy link
Owner

No, that’s not needed.

anyway, glad you found a solution! I’ll close this, don’t hesitate to open something if you find another issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feedback needed Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants