Open In App

How to Use Dagger in a Multi-Module Project in Android?

Improve
Improve
Like Article
Like
Save
Share
Report

We know about the Dagger dependency injection framework and how to use it in a single module project. Dagger is basically used for reducing or completely getting rid of the unnecessary boilerplate code. We have already seen step-by-step usage of the dagger library in android, check it here. But in this article what we are going to learn is much more advance than that. We are going to learn how to use Dagger in multi-module projects but first, we have to understand what is multi-module and what is a single module project and for that let’s consider the following points.

  • What is a single-module project?
  • What is a multi-module project?
  • Designing a multi-module app.
  • Implementing Dagger in the multi-module app.

What is a Single module project?

In Android, a single-module project is a project we normally most often use. In this, we have a single folder managing everything inside it like all the build files and all other subfolders. In short, a single module project is what normally a single developer or a small team of developers uses. In a single module project, we only have one app folder.

What is a Multi-Module Project?

Like in a single module project we have only one app module and we do everything inside that. But in multi-module, we can create multiple app modules and hence we call it a multi-module. In very large scale companies where a large number of employees work using multi-module projects becomes necessary. Initially, you only create a single module project and then add different modules to it and it becomes multi-module. In the below picture you can see we have 2 modules, one is the app module and another is the MyApplication module. Regarding how to create new modules we will see it in the next steps.

Designing a Multi-Module-App

Designing a multi-module project is divided into four modules based on some features or services. Let’s get started by looking at what those modules are.

  • app: Here app is the package created when creating the project.
  • base: It would be a module containing the common code for the project
  • feature-one: It would also be a module containing the code for a specific feature.
  • feature-two: It would also be a module containing the code for another feature.

All the modules will be implemented in the app’s build.gradle as shown below.

implementation project(':base')
implementation project(':feature-one')
implementation project(':feature-two')

And both the feature modules also depend on the base module and will implement in both the feature’s build.gradle file as shown below,

implementation project(':base')

Now let’s see a step by step implementation for creating a multi-module project

Steps by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.

Step 2: Create a New Module

Once your project is created, create a new module as shown below

Just click on the new module button then a screen will appear, on that screen just click next and move ahead keep everything default in that activity. That’s it your new module will get added just by doing this.

Implementing Dagger in Multi-Module App

Step 1: Setting up the Base module

First, we have to set the base module so let’s add dagger dependencies into the build.gradle 

implementation “com.google.dagger:dagger:2.27”

kapt “com.google.dagger:dagger-compiler:2.27”

Step 2: Create a base component and base module

Following is the code for Base Component, just copy and paste it.

Kotlin




@Singleton
@Component(modules = [BaseModule::class])
interface BaseComponent {
    fun inject(app: Application)
    fun getNetworkService(): NetworkService
    fun getDatabaseService(): DatabaseService
}


And below is the code for Base Module.

Kotlin




@Singleton
@Component(modules = [BaseModule::class])
interface BaseComponent {
    fun inject(app: Application)
    fun getNetworkService(): NetworkService
    fun getDatabaseService(): DatabaseService
}


Step 3: Creating Components for Feature 1 and Feature 2

Let’s create feature one component, the feature one component will get its dependency from BaseComponent. Our feature one component will look like,

Kotlin




@FeatureOneScope
@Component(
    dependencies = [BaseComponent::class],
    modules = [FeatureOneModule::class]
)
interface FeatureOneComponent {
    fun inject(activity: FeatureOneActivity)
}


Just like the feature one component, we will now create a feature two-component as given below

Kotlin




@FeatureTwoScope
@Component(
    dependencies = [BaseComponent::class],
    modules = [FeatureTwoModule::class]
)
interface FeatureTwoComponent {
    fun inject(activity: FeatureTwoActivity)
}


Step 4: Component for Main Activity

We also need to create a component for the main activity as shown below

Kotlin




@MainActivityScope
@Component(
    dependencies = [BaseComponent::class],
    modules = [MainActivityModule::class]
)
interface MainActivityComponent {
    fun inject(activity: MainActivity)
}


Step 5: Creating BaseComponentProvider Interface

What we actually want to achieve is to share the exact instance of BaseComponent across the whole application. For that, we have to create a base component provider Interface in our base module as shown below.

Kotlin




interface BaseComponentProvider {
    fun provideBaseComponent(): BaseComponent
}


Step 6: Working with MainActivity

Now we will actually write some working code in MainActivity as we are done setting up Modules and components. MainActivity code will look as follows, Make sure to create the baseComponent interface, without that we will not be able to share the same instance across the application.

Kotlin




class MainActivity : AppCompatActivity() {
  
    @Inject
    lateinit var databaseService: DatabaseService
    
    @Inject
    lateinit var networkService: NetworkService
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        DaggerMainActivityComponent
            .builder()
            .baseComponent(InjectUtils.provideBaseComponent(applicationContext))
            .build()
            .inject(this)
        Log.d("DaggerSample_Main", databaseService.toString())
        startActivity(Intent(this,FeatureOneActivity::class.java))
  
    }
}


Step 7: Working with Feature one and Feature two activity

As feature one and feature two components are already created, we will now create their respective activities and the code in their activities is below.

FeatureOne Activity:

Kotlin




class FeatureOneActivity : AppCompatActivity() {
  
    @Inject
    lateinit var databaseService: DatabaseService
  
    @Inject
    lateinit var networkService: NetworkService
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_feature_one)
  
        DaggerFeatureOneComponent
            .builder()
            .baseComponent(InjectUtils.provideBaseComponent(applicationContext))
            .build()
            .inject(this)
        Log.d("DaggerSample_FeatureOne", databaseService.toString())
  
    }
}


FeatureTwo Activity:

Kotlin




class FeatureTwoActivity : AppCompatActivity() {
  
    @Inject
    lateinit var databaseService: DatabaseService
  
    @Inject
    lateinit var networkService: NetworkService
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_feature_two)
  
        DaggerFeatureTwoComponent
            .builder()
            .baseComponent(InjectUtils.provideBaseComponent(applicationContext))
            .build()
            .inject(this)
        Log.d("DaggerSample_FeatureTwo", databaseService.toString())
  
    }
}


Output:

MainActivity Output: com.example.gfgdemo.base.data.DatabaseService@63d3f1 
FeatureOne Output: com.example.gfgdemo.base.data.DatabaseService@63d3f1

As you can see, both the outputs for MainActivity and FeatureOneActivity are the same, it means in both the activities same instance was used ad that was possible because we created a BaseComponentProvider interface and don’t worry about the DataBaseService objects, those are simple objects of the class just used as an example. So that’s how we use Dagger in a multi-module project.



Last Updated : 20 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads