Multi-module Navigation with Architecture Components

Kurt Acosta picture Kurt Acosta · Jul 10, 2018 · Viewed 7.8k times · Source

So I have this structure for my modules in my current app.

App Module Structure

I haven't found any official documentation on multi-module navigation yet but I found this article regarding this so here's how my gradle files are:

Feature 1 - Detail

...
implementation project(":base")
implementation project(":feature-2-detail")
...

Feature 2 - Detail

...
implementation project(":base")
implementation project(":feature-1-detail")
...

Feature 3 - Detail

...
implementation project(":base")
implementation project(":feature-1-detail")
...

And here are my navigation graphs:

Feature 1 - Detail

<navigation ...
    android:id="@+id/graph_feature_1_id">
    <include app:graph="@navigation/graph_feature_2" />
    <fragment ...
        android:id="@+id/nav_feature_1">
        <action ...
            app:destination="@+id/graph_feature_2_id" />

    </fragment>
</navigation>

Feature 2 - Detail

<navigation ...
    android:id="@+id/graph_feature_2_id">
    <include app:graph="@navigation/graph_feature_1" />
    <fragment ...
        android:id="@+id/nav_feature_2">
        <action ...
            app:destination="@+id/graph_feature_1_id" />

    </fragment>
</navigation>

Feature 3 - Detail

<navigation ...
    android:id="@+id/graph_feature_3_id">
    <include app:graph="@navigation/graph_feature_1" />
    <fragment ...
        android:id="@+id/nav_feature_3">
        <action ...
            app:destination="@+id/graph_feature_1_id" />

    </fragment>
</navigation>

So everything works with this kind of setup but the problem here is that to connect the module to another module, we have to add the other feature as a dependency to the current feature. Like in my case, Feature 1 - Detail can go to Feature 2 - Detail and vice versa and doing this gives me a circular dependency in gradle.

Is there another way to do multi-module navigation? I've tried using deep links but to no avail.

Any help would be appreciated! Thanks!

Answer

Kurt Acosta picture Kurt Acosta · Aug 14, 2019

This is already a year-long but the library now can support this exact use-case! As of 2.1.0-alpha03, we can navigation through deep link URIs.

Instead of adding the features as implementation details to each other, we can leave them unaware between themselves and use deep link navigation.

Feature 1 - Detail - build.gradle

dependencies {
    implementation project(':base')
}

Same with Feature 2 - Detail. No need for it to know the other modules.

To have inter-module navigation, we have to first define the deep link for navigating through that destination via a deepLink tag.

Feature 1 - Detail - Navigation Graph

<navigation ...
    android:id="@+id/graph_feature_1_detail_id">
    <fragment ...
        android:id="@+id/nav_feature_1_detail">
        <deepLink app:uri="myApp://feature1detail"/>

    </fragment>
</navigation>

Feature 2 - Detail - Navigation Graph

<navigation ...
    android:id="@+id/graph_feature_2_detail_id">
    <fragment ...
        android:id="@+id/nav_feature_2_detail">
        <deepLink app:uri="myApp://feature2detail"/>

    </fragment>
</navigation>

Now that we have deep links with URIs set, we can directly use this in a NavController

So in the fragment in Feature 1 - Detail, maybe on a button click? Anywhere where you have to perform navigation

class Feature1DetailFragment {
   fun onViewCreated(...) {
       ...
       view.setOnClickListener {
           val uri = Uri.parse("myApp://feature2detail")
           findNavController().navigate(uri)
       }
   }
}

And in Feature 2 - Detail,

class Feature2DetailFragment {
   fun onViewCreated(...) {
       ...
       view.setOnClickListener {
           val uri = Uri.parse("myApp://feature1detail")
           findNavController().navigate(uri)
       }
   }
}

And voila! Inter-module navigation.

At the time of writing, the latest stable release is 2.1.0-rc01.

Although I haven't tried this out on more complex projects, I love this library and I'm hoping to see this library mature more!

I created a Medium article about this. You can take a look at it. Cheers!