In the previous article of the series Dagger Android : Defeat the Dahaka, we looked at the @Singleton and @Reusable scopes. In this article, let’s try to Face the Beast by diving a little more into the ocean of generated classes and try to learn the patterns involved. Gear up to Unleash the Beast and to even lose your mind in the process 😛

“Once upon a time there lived a developer known as The Droid of Asia, who was curious to see the Face of Dependencies. She started with the simplest implementation of AppComponent and ended up meddling with the generated code and getting chased by “The Dahaka”. From the very first day when she came across a term called Subcomponent , she kept procrastinating to learn about what component dependencies actually were, until one day Google unleashed the sands and introduced Dagger-Android . She went through it’s documentation and it was full of Subcomponents . After a few google searches and Stack Overflow reads later, she realised that the understanding that she was trying to gain wouldn’t come without a price. She knew that she needed to begin her adventures with the component dependencies before she tries to decode all the cryptic stuff related to DaggerAndroid . That’s where it all began.”

Let’s first start with something which can be described without much insanity :

When you first start using Dagger, you usually start out with a single AppComponent and a single AppModule with @Singleton scope. In this case, Dagger generates a DaggerAppComponent which has a HAS-A relationship with AppModule. DaggerAppComponent has-a appModule instance.

But as the size of your app grows, you soon realise that your AppModule is starting to turn into a god module with all sorts of dependencies. That’s when you start looking into different approaches to solve this problem.

I have mainly seen three different types of Component Dependencies :

Single Component, Multiple Module :

When your main god component is getting extremely big and is declaring all sorts of dependencies inside AppModule itself, you can then start splitting it up into pieces like AppModule, ApiModule , etc. Remember all these dependencies would still have Singleton scope (if specified). Both the below mentioned ways are mostly the same and the generated DaggerAppComponent will have a HAS-A relationship with both your modules.

DaggerAppComponent HAS-A appModule.

DaggerAppComponent HAS-A apiModule.

There are two ways of achieving this :

AppComponent declares dependency on both AppModule and ApiModule .

@Component(modules = {AppModule.class, ApiModule.class})

public interface AppComponent

OR

2. AppComponent declares a dependency on only AppModule and AppModule includes ApiModule .

@Component(modules = AppModule.class)

public interface AppComponent @Module(includes = ApiModule.class)

public class AppModule

But, there’s a problem with this approach. There’s still no way of creating custom-scope here and letting some of the dependencies live only for a short while like @ActivityScope , @FragmentScope , @UserScope , etc.

2. Subcomponent Dependency

When you realise that your dependencies need not necessarily live as long as your application lives, you can create a subcomponent. A subcomponent can access any dependency provided in the super component without the need of declaring it explicitly. Example: @ActivityScope or @FragmentScope , the scope of such dependencies is tied to the scope of your Activity or Fragment and is narrower than the scope of the application. We will have a look at subcomponents in detail in the next section.

3. Dependent Component

Creating dependent components is another way of letting your dependencies live for a shorter scope. Example: some dependencies like the User object itself will live only after the user logs into the app and until the time he/she logs out. In this case we can create a component called UserComponent dependent on AppComponent and with a custom scope @UserScope . In this case the dependent component can only access explicitly exposed dependencies from the other component via an interface. Dependent Component lives as an independent object.

Subcomponent vs Dependent Component

UserScope :

She, the Droid of Asia, had heard the term UserScope many times but couldn’t completely implement it herself until she stumbled upon a great article on UserScope by Miroslaw Stanek. This article gave her direction and enabled her to continue her adventures with Dagger 2. She began diving into the generated classes one by one and was chased by “The Dahaka” many times in the process.

Scope as mentioned in the previous article on Scopes is the lifetime of any object / dependency. So, UserScope is the scope of all the dependencies related to any user. Let’s build an example app which demonstrates various component dependencies using the concept of UserScope.

We will be using the example of a Pokemon app to learn the difference between a subcomponent and a dependent component. You can find all the demo code uploaded here. Kotlin version here.

We are going to defeat the Dahaka using cute Pokemons! :P

Let’s have a look at the diagram below to understand what we are trying to build :

Scoping Architecute for the Pokemon app

Let’s start reading our diagram / source code.

AppComponent (@Singleton) : Singleton scoped component, main component of the app. Usually created and persisted in Application class. LoginComponent @ActivityScope : Subcomponent of AppComponent . This contains any dependencies specific to the LoginActivity . UserComponent @UserScope : Dependent on AppComponent . Contains any dependencies related to a user (Pokemon). This component also contains two other @ActvityScope Subcomponents : HomeComponent and ItemsComponent . HomeComponent @ActivityScope : Subcomponent of UserComponent . It also consists of three Fragments : ProfileFragment, StatsFragment and MovesFragment . ItemsComponent @ActivityScope : Subcomponent of UserComponent .

Here’s a running example of how our UserScope looks like :

UserScope

In this article, we are going to focus on two main cases. :

Dependent Component : UserComponent dependent on AppComponent . Subcomponent : LoginComponent is a Subcomponent of AppComponent

Subcomponent vs Dependent Component

We have our AppComponent which exposes a dependency called schedulerProvider . Dagger will generate an implementation of our AppComponent called DaggerAppComponent . UserComponent is dependent on AppComponent and accesses schedulerProvider using the AppComponent interface. LoginComponentImpl is a subcomponent of our AppComponent . Let’s look at the code for the above structure.

AppComponent

We have a @Singleton AppComponent which exposes schedulerProvider() . It also exposes a Builder for LoginComponent (We will use this later).

DahakaApplication

Our DahakaApplication is responsible for creating the AppComponent .

Dependent Component

UserComponent

dependencies = arrayOf(AppComponent::class) : This is how we tell dagger that UserComponent is dependent on AppComponent . We declare a @Component.Builder inside UserComponent . This tells dagger to generate a Builder implementation according to our specifications. More about Component.Builder here. @BindsInstance binds our user : Pokemon to the Object Graph. More about @BindsInstance here.

UserManager

UserManager is a singleton dependency. After we login, we get a Pokemon instance from server which is our User. We start the session by building our UserComponent . Note that we need to provide an instance of our appComponent to the UserComponent to access dependencies like schedulerProvider . Pokemon will be bound to the object graph, so that it’s available in the @UserScope .

DaggerUserComponent (Generated)

Let’s have a look at the “Face of the Dahaka” by walking through the generated DaggerUserComponent .

We have a few things to note here :

Whenever we declare a dependency SomeDependency , Dagger stores a Provider<SomeDependency> inside the component implementation. Thus, in the above case, dagger stores a Provider<BaseSchedulerProvider> schedulerProvider. Inside the initialize() function for our DaggerUserComponent , Dagger initializes the schedulerProvider using the appComponent that we previously passed in our builder while creating UserComponent . Whenever any dependency will need schedulerProvider , dagger will call schedulerProvider.get() which will eventually get the dependency using the AppComponent instance. We can not access the schedulerProvider dependency from within the UserComponent . We use the AppComponent interface to access any dependency from the @Singleton scope. This is why we had to expose our schedulerProvider() dependency inside AppComponent.

SubComponent

Login Subcomponent

LoginComponent has @ActivityScope as it’s bound to the LoginActivity . We tell dagger that this is a Subcomponent using the annotation @Subcomponent . Just like a @Component.Builder , we can also tell dagger how the Builder for this subcomponent should look like. We tell dagger to bind the instance of LoginActivity to the graph using the @BindsInstance annotation.

LoginActivity

We build our LoginComponent inside our LoginActivity using the Builder that we declared earlier inside our LoginComponent . We can get the exposed Builder appComponent.loginbuilder() from AppComponent .

DaggerAppComponent (Generated)

Let’s have a look at the “Face of the Dahaka” by walking through the generated DaggerAppComponent .

There are a few things to note here :

Dagger generates a LoginComponentBuilder which implements the LoginComponent.Builder that we declared inside the LoginComponent . Dagger instantiates a Provider<LoginComponent.Builder> . Final and the most important thing to note here : Dagger generates a LoginComponentImpl which is an inner-class of the DaggerAppComponent . Any AppComponent dependency needed by the LoginComponentImpl can be directly accessed from the AppComponent without the need of explicitly exposing those dependencies since an inner-class can access the members of it’s outer class.

Dependent Component vs Subcomponent TL;DR

Let’s connect the dots now by visiting the diagram again below :

Dependent Component vs Sub component

DaggerUserComponent

DaggerUserComponent is dependent on the AppComponent .

is on the . DaggerUserComponent doesn’t know about the implementation of AppComponent , it only knows about the dependencies exposed via the AppComponent interface.

doesn’t know about the implementation of , it only knows about the dependencies exposed via the interface. DaggerUserComponent accesses schedulerProvider using the AppComponent interface.

LoginComponentImpl

LoginComponentImpl is a subcomponent of AppComponent .

is a of . LoginComponentImpl is generated as an inner-class of DaggerAppComponent .

is generated as an inner-class of . LoginComponentImpl can directly access any dependency of the AppComponent , without the need of explicitly exposing it in the AppComponent interface.

Conclusion

Use dependent components, when you want to keep the two components independent and to keep less coupling between the two.

Use subcomponents when the two components are coupled with each other like in the case of Application and Activity . Also, dagger-android plays well with subcomponents and can reduce the boilerplate for Android Framework classes such as Activity , Fragments , Services , etc. More about dagger-android in upcoming posts.

Thanks Lucia Payo for the review :)

I also gave a talk about “Dagger 2 Android : Defeat the Dahaka” at Droidcon Berlin, 2017.

Checkout the video :

If you find something which doesn’t make sense, kindly leave a comment.

Stay tuned for the whole series :)