Hi <@U0234N0QYSK> , I’m currently using Compose D...
# compose-destinations
y
Hi @Rafael Costa , I’m currently using Compose Destinations in my app. It’s truly a wonderful library. I am trying out version 2 and was wondering if you could explain, at your convenience, how to aggregate NavGraphs in a Multi Module application setup. https://composedestinations.rafaelcosta.xyz/v2/multi-module-setup More details follow in the thread
In version 1, by setting the mode as shown below, it was possible to automatically generate Graphs published by feature modules and reference them from another module to aggregate the NavGraph. build.gradle.kts:
Copy code
ksp {
    arg("compose-destinations.moduleName", "hoge")
    arg("compose-destinations.mode", "navgraphs")
}
Navigation module:
Copy code
object MainNavGraph : NavGraphSpec {
    override val route = "main"
    override val destinationsByRoute = emptyMap<String, DestinationSpec<*>>()
    override val startRoute = HogeNavGraph
    override val nestedNavGraphs = listOf(
        HogeNavGraph,
        FugaNavGraph,
        OtherNavGraph,
    )
}
In version 2, my understanding is that to do something similar, one needs to manually prepare the NavGraphs to be published and associate all the Destinations that should be included in that graph. Is this correct? If there is a simpler way to publish them, similar to version 1, I would like to know. HogeGraph:
Copy code
@NavGraph<ExternalModuleGraph>
internal annotation class HogeNavGraph
HogeRoute:
Copy code
@Destination<HogeNavGraph>
@Composable
fun HogeScreen(...){...}
Navigation module:
Copy code
@NavHostGraph
annotation class MainGraph {
    @ExternalNavGraph<HogeNavGraph>
    @ExternalNavGraph<FugaNavGraph>
    @ExternalNavGraph<OtherNavGraph>
    companion object Include
}
It seems that the “RootNavGraph” on the Feature Module side is published without doing the above. However, because it includes the “root” Destination, using it might result in runtime errors when aggregating NavGraphs.
r
Hi @yurihondo! Glad you're enjoying the library! 🙇 I'm not sure I follow exactly what you mean... but the way I look at it, before it was manual, now (on v2) it's a little less manual 😄 Not the other way around. So maybe there's a miss understanding somewhere..
Your feature modules, should create their NavGraphs (in your example HogeNavGraph, FugaNavGraph, OtherNavGraph). The module that is "gathering" them and nesting them into a graph that holds all of them would do what you're saying:
Copy code
@NavHostGraph
annotation class MainGraph {
    @ExternalNavGraph<HogeNavGraph>(start = true) // 👈 ADDED THIS TO BE EQUAL TO THE v1 EXAMPLE
    @ExternalNavGraph<FugaNavGraph>
    @ExternalNavGraph<OtherNavGraph>
    companion object Include
}
rather than on v1:
Copy code
object MainNavGraph : NavGraphSpec {
    override val route = "main"
    override val destinationsByRoute = emptyMap<String, DestinationSpec<*>>()
    override val startRoute = HogeNavGraph
    override val nestedNavGraphs = listOf(
        HogeNavGraph,
        FugaNavGraph,
        OtherNavGraph,
    )
}
On v2, the annotation "MainGraph" would basically generate the one you wrote manually on v1.
right?
One part I didn't understand was this:
It seems that the “RootNavGraph” on the Feature Module side is published without doing the above. However, because it includes the “root” Destination, using it might result in runtime errors when aggregating NavGraphs.
The feature module should not be generating RootNavGraph, unless you are using RootGraph annotation in that module 🤔
y
@Rafael Costa Thank you for your confirmation and response. I apologize for asking a vague question; it was rude of me. What I wanted to ask about was the generation process of the Graph published by the Feature Module. I believe that in v1, by adding ksp settings, a public Graph was generated based on the Destinations linked to the RootNavGraph. However, in v2, it seems necessary to manually create a public Graph and link each Destination, requiring more manual preparation compared to v1. So, is there no method to easily create an externally published Graph like in v1? That was my question. However, upon further consideration, the way v2 handles this, by making the Graph to which a Destination belongs and its scope explicit, seems to be more organized and preferable…
The feature module should not be generating RootNavGraph, unless you are using RootGraph annotation in that module 🤔
I apologize for the lack of explanation🙇‍♂️ I attempted to link the Destinations on the FeatureModule side to the RootGraph in a similar manner to v1, aggregating the generated
RootNavGraph
in the Destination Module’s NavGraph, but it did not work as expected. That comment was about that attempt. I believe that the
RootNavGraph
generated in this way is not intended for aggregation purposes.
r
Oh I get what you mean now! And you were not rude at all ahah. Thank you for bringing this to my attention! 👍 So yeah, on v1 we could have a default nav graph on each module that destinations would belong to. This is removed on v2 given that the graph is now a type arg to the destination annotation. What we could do is we could generate a nav graph with module name when using root graph, but I think the only thing this does is avoiding the need to create annotation class which is two lines of code and does make things more explicit. You would still need to add the RootGraph to each destination annotation. So I am inclined to think that option is not great. Do you think this additional work is considerable? So basically one annotation class and adding that to each destination annotation of that module?
There is a way to create your own Destination annotation with nav graph information. So you could do that and then instead of
@Destination<MyGraph>
you could do
@MyGraphAnnotation
. Not sure it’s worth it though, it’s almost the same number of characters. ( your destination could have a smaller name, but I guess including the name of the graph is what would make sense imo). If you want to try that you can check this: https://composedestinations.rafaelcosta.xyz/v2/defining-destinations#centralizing-destination-annotation-configuration (second example)
y
Sorry for late reply 🙇‍♂️ Thank you for your kind explanation. I understand now. My app has over 10 feature modules and more than 80 destinations, so I was hoping to learn if there was a method similar to v1 for transitioning to v2. It’s clear that the way of writing in v2 is more understandable, so I will consider the method you introduced and proceed to rewrite it to the new format. Aside from the questions I’ve asked this time, I have some feedback about transitioning to v2, so I will reach out again using a specific method, such as through GitHub Issues or here. Once again, it’s a fantastic library. I will continue to support it.
👍 1
r
No worries at all @yurihondo ! I’m happy to take any feedback here or on GitHub as you wish 🙂