Easy Setup of Dagger2 and other Components in a Multi-module App using Clean Architecture

In my last article, I explained the migration of a single module to a multi-module using Clean Architecture and how it was structured.

In this part, I would like to share how I set up the codebase using Dagger2, Jetpack components (Navigation, Room), and Kotlin Coroutines in a simple process.

Scope

Like I mentioned previously, I will try as much as possible to avoid long read rather nosedive into the main business of the day—code setup.

Project Structure

Now that we have our modules structured as described in the last article alongside their respective contents, I will explain the code according to the modules and/or layers.

Setting up of Dagger2 in the core module:

@Compnent.Factory provides an easy way to provide application context into an object graph by annotating its parameter in a single method instead of individual methods (like that of @Component.Builder).

Since this is a multi-module, aside from the core component in the core module, each feature module has its own component with the core component as a dependency. In the core module, there are just the CoreComponent and CoreModule as our dependency injection classes. Here we could provide the DatabaseModule the application context. Also, in this module, I have the MainApplication class.

Below are the snippets of the CoreComponent , CoreModule , and MainApplication classes respectively.

The reason for initialising the repository class is that it is used across the feature modules, hence, it needs to publicly provided.

Here is how we create it in the application class:

From the above code gist, the two methods are created in order to inject DaggerComponent in the Activity and Fragment classes of each module.

Check here to learn more about the @Component.Factory and other old ways of providing application context into an object graph.

Does this look easier? I guess, yes. So, let’s dive into creating the dagger component for each module. I will provide for a module.

For the competition module, this is how the component looks like:

The ViewModel classes are provided in the usual way in the CompetitionsViewModelModule class as seen below:

And this is how it’s injected in the fragment:

Setting up the Navigation Graphs in the navigation module:

I mentioned in my last article that all the navigation classes are pulled together in a module to be accessed across all the modules.

Now, let’s see how the design looks like:

On the first page (i.e. the fixtures and competitions fragments), the graph has a separate layout (for competitions module).

The second page (that contains the viewpager in the competitiondetails module) has only the viewpager fragment class nav graph while the respective fragments in the viewpager are implemented in the usual way.

See the implementation below:

I know you’ve got some questions in mind like “since there are many feature modules, which one hosts the navigation graph”?

Well, the whole app uses a single activity pattern, so, the activity_main hosts the navigation graph in the app module. All settings relating to the navigation is done in the HomeActivity.kt class as shown below:

What is contained in the data module

This module contains set up for room, coroutine dispatcher, repository implementation (which implements the repository interface defined in the domain layer/module) and of course where all these are provided (for dagger usage) in the DataModule and NetworkModule classes.

I’m not able to include all the codes in this article but rest assured that you will find them here.

Conclusion

With the above steps, we have been able to set up some components (dagger2, navigation, etc.) with CA in a multi-module app.

And yes, you can check out an article I wrote about how I migrated this project to using hilt.

Thanks for reading through!

If you have any comment, kindly drop it in the comment section below and if you ❤️ this article, please feel free to 👏 and share.

Android Developer | Occasional Writer