[HOW-TO] Android Dagger (2.11–2.17) Butterknife (8.7-8.8) MVP (Part 1)

Welcome to a complete guide to making Dagger.Android (2.11–2.17), ButterKnife (8.7-8.8), and Model-View-Presenter (MVP) all work together in harmony.
This is Part 1 of a 3-part series:
- Creating a project, from scratch, using the new Dagger.Android (2.11-2.17) dependency injection framework with support for
@Singleton
,@PerActivity
,@PerFragment
, and@PerChildFragment
scopes. [ISSUES] - Using ButterKnife (8.7-8.8) to replace a lot of handwritten boilerplate view binding code. [ISSUES]
- Restructuring the code to Model-View-Presenter (MVP) to increase testability, maintainability, and scalability. [ISSUES]
UPDATES
This article and its companion Github Project are occasionally updated and are compatible with the newest versions of Dagger 2 (2.11-2.17) and Butterknife (8.7-8.8).
Kotlin branches are now available: [master-kotlin], [master-support-kotlin]
Before we begin…
There are a couple of things to clarify before we begin.
This is a how-to article, not a history lesson. This article will not answer the following questions:
- What is Dagger 2?
- How is Dagger 2 different from Dagger 1?
- What is a common setup for Dagger 2 projects before version 2.10?
- Are there other dependency injection frameworks out there?
- What is dependency injection?
If you do not know the answer to any of the questions above, then Google it. These questions have already been answered many times before by many different people. They will not be addressed in this guide for brevity.
The only question I will answer is “what is dagger.android that is introduced in version 2.10?”. Dagger 2.10 introduced the dagger.android framework that greatly simplifies dependency injection in Android and gets rid of a lot of boilerplate dependency injection code that exists in previous versions.
Tip: If you didn’t know already, Dagger 2 can be used in pure, non-Android, Java projects / modules).
This article focuses on using Dagger 2.11, which contains something very useful called @ContributesAndroidInjector
(more on this later).
The official Google user guide for dagger.android is at https://google.github.io/dagger/android.html. However, the user guide may be difficult to understand and lacks useful examples. There are few blogs out there that introduces the new dagger.android framework with some examples to get your feet wet. However, I have yet to read an article that attempts to and successfully answers the following question:
How to create an Android application that uses Dagger Android (2.11-2.17), Butterknife (8.7-8.8), and Model-View-Presenter (MVP) with support for Singleton, Activity, Fragment, and child Fragment scopes?
Read this guide to find out!
This guide is a complete guide with code snippets and explanations. Therefore, it is quite lengthy. However, it will teach you everything you need to know for a complete dagger.android, Butterknife, and MVP setup so grab some coffee (or tea) and start reading!
Companion GitHub project
The GitHub project for this series is at https://github.com/vestrel00/android-dagger-butterknife-mvp, which is built specifically for this guide. Each section of this guide corresponds to an issue, which is closed by a single pull request (PR) and tagged in chronological order.
If you are an experienced developer with Dagger 2, you could probably skip reading this article and explore the GitHub project.
This article will walk you through the following [ISSUES].
Note: The android-dagger-butterknife-mvp project is a smaller, derivative of a larger project. One of the main purpose of this project is to showcase / walkthrough a specific portion of the larger project’s architecture. Take a look at the following larger project for a more real-world example on how to apply Dagger Android (2.11-2.17), Butterknife (8.7-8.8), Clean Architecture, MVP, MVVM, Kotlin, Java Swing, RxJava, RxAndroid, Retrofit 2, Jackson, AutoValue, Yelp Fusion (v3) REST API, Google Maps API, monolithic repo project management with Gradle, JUnit 4, AssertJ, Mockito 2, Robolectric 3, Espresso 2, and Java best practices and design patterns.
A Gist overview
For a quick overview of dagger.android 2.11 usage with support for @Singleton
, @PerActivity
, @PerFragment
, and @PerChildFragment
scopes, take a look at this gist. Keep reading for the complete guide with proper step-by-step setup and explanations.
Creating a project, from scratch, using the new dagger.android (2.11) framework
With all of that out of the way, it’s time to dive into part 1, which is split into 9 steps:
- Initializing the Android Gradle project. [PR|TAG]
- Adding the Dagger (2.11) dependency to the Gradle build script. [PR|TAG]
- Setting up the Dagger injection framework. [PR|TAG]
- Creating scoped utility classes. [PR|TAG]
- Creating the main activity to navigate to the other example activities. [PR|TAG]
- Creating example 1; an Activity with 1 Fragment. [PR|TAG]
- Creating example 2; an Activity with 2 Fragments. [PR|TAG]
- Creating example 3; an Activity with 1 Fragment that contains 1 child Fragment. [PR|TAG]
- Refactoring the subcomponent setup to use the
@ContributesAndroidInjector
annotation. [PR|TAG]
1. Initializing the Android Gradle project. [PR|TAG]
The initial project structure is as follows.

There isn’t much to say at this point. This is just a skeleton Android Gradle project.
Note: This article walks you through dagger.android, Butterknife, and MVP setup for projects with a minimum
minSdkVersion
of 17. Supporting API levels below 17 down to 14 requires the use ofAppCompatActivity
, supportFragment
, and dagger.android.support APIs.Take a look at this [PR] for the migration guide to using support APIs. The latest support API setup is available in the [master-support] branch.
Note: Android Studio 2.3.3 was used at the time of writing these articles. Since 3/12/18, the project has been upgraded to Android Studio 3.2.0 canary 5.
3. Setting up the Dagger injection framework. [PR|TAG]
The dependency injection flow is as follows.
- Application injects Activities
- Activity injects Fragments
- Fragment injects child Fragments
Dependencies are shared from top to bottom. Activities have access to Application @Singleton
dependencies. Fragments have access to Application @Singleton
and Activity @PerActivity
dependencies. Child fragments have access to Application @Singleton
, Activity @PerActivity
, and (parent) Fragment @PerFragment
dependencies.
Note: This guide does not show how to inject Services, IntentServices, BroadcastReceivers, and ContentProviders to keep the guide at a reasonable size. You, the reader, should be able to easily figure this out on your own once you finish reading this guide.
To get started, take a look at the base framework types;
DaggerService
,DaggerIntentService
,DaggerBroadcastReceiver
, andDaggerContentProvider
.
Achieving this flow is straightforward.
First, create the custom scope annotations; @PerActivity
, @PerFragment
, and @PerChildFragment
.
The @PerActivity
scoping annotation specifies that the lifespan of a dependency be the same as that of an Activity. This is used to annotate dependencies that behave like a singleton within the lifespan of an Activity, Fragment, and child Fragments instead of the entire Application.
The @PerFragment
custom scoping annotation specifies that the lifespan of a dependency be the same as that of a Fragment. This is used to annotate dependencies that behave like a singleton within the lifespan of a Fragment and child Fragments instead of the entire Application or Activity.
The @PerChildFragment
custom scoping annotation specifies that the lifespan of a dependency be the same as that of a child Fragment (a fragment inside a fragment that is added using Fragment.getChildFragmentManager()
). This is used to annotate dependencies that behave like a singleton within the lifespan of a child Fragment instead of the entire Application, Activity, or parent Fragment.
Note: This setup does not support a child fragment within a child fragment as conflicting scopes will occur (compile time error). Child fragments within child fragments should usually be avoided. However, if another level of child fragment is required, then another scope would need to be created (perhaps
@PerGrandChild
custom scope annotation).
There is no @PerApplication
custom scope annotation. @Singleton
is used to specify that the lifespan of a dependency be the same as that of the Application.
Question: Why not create a
@PerApplication
custom scope instead of using@Singleton
?Third party libraries / dependencies use
@Singleton
, if they use dependency injection. If you use@PerApplication
instead of the standard@Singleton
scope, then Dagger will not be able to automatically inject@Singleton
scoped dependencies.
Next, create the App
, AppModule
, and AppComponent
, which is the entry point of the entire dependency injection setup.
The entry point of all dependency injection is the App
, which implements HasActivityInjector
that provides a dagger injected DispatchingAndroidInjector<Activity>
. This indicates that activities are to participate in dagger.android injection.
The top-most level injection occurs in onCreate
with DaggerAppComponent.create().inject(this)
, which is a class that is generated by Dagger during compile-time based on the AppComponent
.
Note: The
App
could extendDaggerApplication
instead of implementingHasActivityInjector
. However, inheritance should be avoided so that the option to inherit from something else later on is open. E.G. theApp
needs to extendMultiDexApplication
(multidex is not a great example here since the application can install it without having to extend it- it’s just a hypothetical).The base framework type
DaggerApplication
contains a lot more code than what we have, which is not necessary unless we need to inject aService
,IntentService
,BroadcastReceiver
, orContentProvider
(especiallyContentProvider
). In the case that we do need to inject other types besidesActivity
andFragment
or if you know that yourApplication
does not need to extend something else, then it may be worth it to just extendDaggerApplication
instead of writing more dagger code ourselves.
The AppModule
is an abstract class that is annotated with the @Module
annotation and includes the AndroidInjectionModule
, which contains bindings to ensure the usability of dagger.android framework classes. The AppModule
is empty right now but we will add stuff to it later.
The AppComponent
is annotated with @Component
and @Singleton
to indicate that its modules (AppModule
) are to provide @Singleton
scoped or unscoped dependencies.
Next up is to create the base classes to be used throughout the app; BaseActivity
, BaseActivityModule,
BaseFragment
, BaseFragmentModule
, and BaseChildFragmentModule
.
The BaseActivity
contains dagger.android code that is very similar to the code in App
. The only difference is that the BaseActivity
implements HasFragmentInjector
, indicating that fragments are to participate in dagger.android injection.
Note: The
BaseActivity
could extendDaggerActivity
instead of implementingHasFragmentInjector
. However, inheritance should be avoided so that the option to inherit from something else later on is open.Note: For support
Fragment
andAppCompatActivity
users, take a look at this [PR] for the migration guide to using support APIs. The latest support API setup is available in the [master-support] branch.Question: Why is
FragmentManager
injected into theBaseActivity
? Why not just use thegetFragmentManager()
method?Short answer is to enable ease of mocking and verification in tests. Read this [PR] for a more detailed answer.
The injection occurs in onCreate
before the call to super.
A FragmentManager
named BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER
is also injected. The name is necessary here to avoid conflicts between the activity’sFragmentManager
and the fragment’s child FragmentManager
during injection.
Note: We may also create our own custom
@Qualifier
instead of using@Named
to distinguish between the Activity and Fragment (child)FragmentManager
. I wrote a long rant discussing@Qualifer
and@Named
and the advantages / disadvantages of each here.
The addFragment
method provides subclasses the ability to add fragments. This is unused now but will be used later on.
Question: What is that
@IdRes
annotation forint containerViewId
?
@IdRes
is a part of the Android support annotations library that “denotes that an integer parameter, field or method return value is expected to be an id resource reference”. For a full list of support annotations, click here.The Android support annotations library comes with our Dagger 2.11 and Butterknife 8.7 dependencies. However, you should declare the support annotations library as a separate dependency. Visit the official documentation to learn more.
The BaseActivityModule
provides the base activity dependencies; the activity Context
and the activity FragmentManager
named ACTIVITY_FRAGMENT_MANAGER
. The module of the subclasses of the BaseActivity
are required to include the BaseActivityModule
and provide a concrete implementation of the Activity. An example of this will be shown later.
Question: I am getting a runtime error,
IllegalStateException module must be set
, after making some modifications to this project. How do I fix it? What is@Binds
? How is it different from@Provides
?The most likely issue is that you are attempting to use
@Provides
on a non-static method of an abstract module. Read more about it here. In that article, I also explain what@Binds
is and how its different from@Provides
.Note: Scoping the
Context activityContext(Activity activity)
with@PerActivity
is not necessary since theActivity
instance will always be unique (new instances of it will not be created even without any scope). In general, providingApplication
,Activity
,Fragment
,Service
, etc does not require scoped annotations since they are the components being injected and their instance is unique.The same thing applies to
static FragmentManager activityFragmentManager(Activity activity)
. TheActivity
instance is unique so theFragmentManager
it returns always come from the sameActivity
. Thus, the@PerActivity
is not necessary here as the scope is implicitly per activity (literally).However, using scope annotations in these cases makes the module easier to read. We wouldn’t have to look at what is being provided in order to understand its scope. I choose readability and consitency here over (negligible) “performance/optimization”. (Yes, I read up on the DoubleCheck wrapper around scoped dependencies and its one time synchronization block. I still abide by my statement given the following suporting materials; [1], [2]. I don’t want to digress further but essentially the synchronization cost only comes into play when multiple threads attempt to access the same locked resource at the same time. Most dependency injection setups do not incur this synchronization penalty as injection usually happens in only one thread.)
The BaseFragment
, like the BaseActivity
, implements HasFragmentInjector
indicating that child fragments are to participate in dagger.android injection.
Note: The
BaseFragment
could extendDaggerFragment
instead of implementingHasFragmentInjector
. However, inheritance should be avoided so that the option to inherit from something else later on is open.Question: What about
DialogFragments
? How are they injected?Someone has asked this question here, which I have answered here.
Question: Why is activity
Context
and childFragmentManager
injected into theBaseFragment
? Why not just use thegetContext()
andgetChildFragmentManager()
methods respectively?Short answer is to enable ease of mocking and verification in tests. Read this [PR] for a more detailed answer.
The injection occurs in onAttach
before the call to super.
Note: We place
AndroidInjection.inject(this)
inonAttach(Context)
for Android versions M (API level 23) and above and also inonAttach(Activity)
for Android versions L (API level 22) and below. The reason is thatonAttach(Activity)
has been deprecated starting at API level 23. Do not only perform the injection inonAttach(Context)
because it will not be invoked by devices running Lollipop (API level 22) and below, which will cause aNullPointerException
when trying to accessFragment
dependencies. I have learned this the hard way. Take a look at this [BUG] and the [BUGFIX].Another thing to note is that using support
Fragment
does not require the above API level checks. We would only need to callAndroidSupportInjection.inject(this)
inonAttach(Context)
because support Fragments have and invokesonAttach(Context)
even for API level 22 and below, which makes sense given that the entire goal of the support libs is to give older versions of Android code that’s available only in newer API levels.Take a look at this [PR] for the migration guide to using support APIs. The latest support API setup is available in the [master-support] branch.
The activity Context
, which is provided by the BaseActivityModule
, is injected here as well as a FragmentManager
named BaseFragmentModule.CHILD_FRAGMENT_MANAGER
. As previously mentioned in the BaseActivity
, the name is necessary here to avoid conflicts between the activity’sFragmentManager
and the fragment’s child FragmentManager
during injection.
The addChildFragment
method provides subclasses the ability to add child fragments. This is unused now but will be used later on.
Child fragments also extend BaseFragment
to avoid code duplication, which will become more apparent when refactoring to Model-View-Presenter (MVP) architecture later on. The trade-off is that child fragments will have access to the childFragmentManager
and addChildFragment
, which should not be used by child fragments unless grandchildren (child fragment within a child fragment) are supported.
The BaseFragmentModule
provides the base fragment dependencies; so far only the child FragmentManager
named CHILD_FRAGMENT_MANAGER
. The module of the subclasses of the BaseFragment
are required to include the BaseFragmentModule
and provide a concrete implementation of the Fragment named FRAGMENT
. An example of this will be shown later.
Note: Similar to the
BaseActivity
andBaseFragment
FragmentManager
names, a different name for the Fragment dependency is required in order to remove any ambiguity about which fragment is being provided in a child fragment.For example, we have parent fragment P and child fragment C. Parent fragment P will provide the Fragment reference using the
BaseFragmentModule.FRAGMENT
name whereas child fragment C will provide the Fragment reference using theBaseChildFragmentModule.CHILD_FRAGMENT
name.If the parent and child fragment dependencies are not uniquely named, then the child fragment and its dependencies will not know which Fragment is provided to it because both dependencies have the same type of
Fragment
. It could be the parent fragment or the child fragment. Hence the ambiguity, which causes a compile error of "android.app.Fragment is bound multiple times".Note: The
Fragment.getChildFragment()
method is only available beginning with API level 17. Supporting API levels below 17 down to 14 requires the use ofAppCompatActivity
, supportFragment
, and dagger.android.supportAPIs.Take a look at this [PR] for the migration guide to using support APIs. The latest support API setup is available in the [master-support] branch.
The BaseChildFragmentModule
provides the base child fragment dependencies. The module of the subclasses of the BaseChildFragment
are required to include the BaseChildFragmentModule
and provide a concrete implementation of the Fragment named CHILD_FRAGMENT
. An example of this will be shown later.
4. Creating scoped utility classes. [PR|TAG]
In order to test the different scopes (@Singleton
, @PerActivity
, @PerFragment
, and @PerChildFragment
), we will create a “utility” class that is provided using each scope; SingletonUtil
, PerActivityUtil
, PerFragmentUtil
, and PerChildFragmentUtil
.
The SingletonUtil
is scoped with @Singleton
. This means that the Application and all Activities, Fragments, and child Fragments and their dependencies will share the same single instance of this class.
A default, package-private constructor is provided and annotated with @Inject
in order to automatically provide an instance of this class without having to manually create a new instance of it.
The doSomething()
method returns the instance’s hashCode
. This will be used later on to verify that the same instance is used in all Activities, Fragments, and child Fragments.
Question: What if I want the
SingletonUtil
to hold a reference to theApplication
/ ApplicationContext
? In other words, how do I provide the Application / Application Context to Singleton dependencies?I have created an [ISSUE] for this question and have a working solution as seen in this [PR]. The answer is to use
@BindsIntance
in theAppComponent
@Component.Builder
in order to bind / provide the Application instance.UPDATE: A better way to provide the Application context has been found. Take a look at this [PR]. This improved version uses
AndroidInjector<App>
andAndroidInjector.Builder<App>
to provide theinject(App app)
method andApp
instance for us instead of writing it ourselves as we did when using the@BindsInstance
approach. This approach is more in line with dagger.android injection as we will see in the following sections of this article.
The PerActivityUtil
is scoped with @PerActivity
. This means that the Activity and all of its Fragments and child Fragments and their dependencies will share the same instance of this class. However, different activity instances will have their own instances. This is not available at the Application level.
The doSomething()
method returns the instance’s and activity’shashCode
. This will be used later on to verify that the same instance is used in all Fragments and child Fragments of each Activity though each Activity will have their own instance.
The PerFragmentUtil
is scoped with @PerFragment
. This means that the Fragment and all of its child fragments and their dependencies will share the same instance of this class. However, different fragment instances will have their own instances. This is not available at the Activity and Application level.
Note: Notice that the name of the Fragment in the constructor is
BaseFragmentModule.FRAGMENT
. Scroll up to read an explanation surrounding this name.
The doSomething()
method returns the instance’s and fragment’s hashCode
. This will be used later on to verify that the same instance is used in all child Fragments of each (parent) Fragment though each (parent) Fragment will have their own instance.
The PerChildFragmentUtil
is scoped with @PerChildFragment
. This means that the child Fragment (a fragment inside a fragment that is added using Fragment.getChildFragmentManager()
) and all of its dependencies will share the same instance of this class. However, different child fragments instances will have their own instances of this class. This is not available at the (parent) Fragment, Activity, and Application level.
Note: Notice that the name of the Fragment in the constructor is
BaseChildFragmentModule.CHILD_FRAGMENT
. Scroll up to read an explanation surrounding this name.
The doSomething()
method returns the instance’s and child fragment’s hashCode
. This will be used later on to verify that no same instance is used in different child fragments.
5. Creating the main activity to navigate to the other example activities. [PR|TAG]
Now we’ll create an activity that provides a way to navigate to 3 other example activities. The MainActivity
will contain a fragment, the MainFragment
, which contains 3 buttons; 1 button for each of the 3 example activities. The MainActivity
simply hosts the MainFragment
and listens to button clicks from the MainFragment
through a listener interface.
First, start by creating the MainFragment
, MainFragmentListener
, MainFragmentModule
, and MainFragmentSubcomponent
.
The MainFragment
extends our BaseFragment
and listens to the click events from 3 buttons declared in the main_fragment
layout. The MainFragmentListener
methods are invoked in accordance to the click events.
Why not just put the layout of this fragment into the Activity itself? We could do that. However, we would lose the ability to reuse this fragment along with other fragments in different activities if we wanted to. The activity only acts as the host to 1 or more fragments for inter-fragment communication. All views and logic are in fragments. This leads to a modular and reusable architecture as well as a simpler MVP architecture, which we will do later.
Note: There is a lot of view binding code here. Finding the views in
onViewCreated
to set their click listeners and implementing theView.OnClickListener
with a big switch statement. All of this code will be heavily simplified later when using Butterknife.
The MainFragmentListener
simply defines the methods that are invoked when the buttons are clicked.
The MainFragmentModule
includes the BaseFragmentModule
and provides a concrete fragment, in this case the MainFragment
, as per the contract specified in BaseFragmentModule
.
The MainFragmentSubcomponent
extends AndroidInjector<MainFragment>
and specifies that the MainFragmentModule
be used to provide its dependencies and that the Builder
build the subcomponent instance that will inject those dependencies into the MainFragment
. The subcomponent is annotated with @PerFragment
indicating that the specified modules provides @PerFragment
scoped and non-scoped dependencies.
This MainFragmentSubcomponent
interface is used by Dagger to inject dependencies to the MainFragment
. Notice that the Builder
is really barebones. This will allow later on to use @ContributesAndroidInjector
to automatically provide the subcomponent injectors, thereby removing the need to have @Subcomponent
classes.
Note: The
Builder
is empty in our uses of it. They are usually used if there are dependencies that need to be injected at runtime instead of compile-time. Read the official user guide to find out more.
Next, create the MainActivity
, MainActivityModule
, and MainActivitySubcomponent
.
The MainActivity
extends our BaseActivity
and implements the MainFragmentListener
interface where a Toast
is made to each interface method invocation. We will replace these placeholder toasts with code to start our example activities later.
The MainFragment
is added in onCreate
into the fragment_container
.
Tip: Adding fragments may also be done in the xml layout by declaring the fragment class using the <fragment> tag.
The MainActivityModule
includes the BaseActivityModule
and specifies that the MainFragmentSubcomponent
is a subcomponent of this module (thereby gaining access to this activity’s, and in turn the application’s, dependencies).
The mainFragmentInjectorFactory
method takes in the MainFragmentSubcomponent.Builder
and returns the AndroidInjectorFactory
. This provides the injector for the MainFragment
.
The activity
method takes in a concrete activity, in this case MainActivity
, as per the contract specified in BaseActivityModule
.
The mainFragmentListener
takes in the MainActivity
, which implements MainFragmentListener
, and binds it into the MainFragment
that expects a MainFragmentListener
to be injected.
The MainActivitySubcomponent
is quite similar in structure to MainFragmentSubcomponent
. It extends AndroidInjector<MainActivity>
and specifies that the MainActivityModule
be used to provide its dependencies and that the Builder
build the subcomponent instance that will inject those dependencies into the MainActivity
. The subcomponent is annotated with @PerActivity
indicating that the specified modules provides @PerActivity
scoped and non-scoped dependencies.
This subcomponent, along with all other subcomponents as previously mentioned, will be replaced with @ContributesAndroidInjector
later on.
Note: Things like adding the activity in the
AndroidManifest.xml
, creating themain_activity.xml
andmain_fragment.xml
layouts, etc, have been left out of this article for brevity. If you want to see these excluded things, then take a look at the [PR]. You may also take the project for a spin at this state by checking out the [TAG]. In general, every section of this article has a corresponding PR and TAG for use at your convenience.
Next, update the AppModule
to provide the injector for the MainActivity
.
The mainActivityInjectorFactory
provides the injector for the MainActivity
. The MainActivitySubcomponent
has also been added as a subcomponent in the @Module
subcomponents
field.
Question: Why not put injectors into a “Builders” module?
I’ve read some blogs that showcase dagger.android injection. Those blogs places injectors in a module called
BuildersModule
, which is included in the app module. This only works if the injectors provided in theBuildersModule
are of the same scope (e.g.@PerActivity
) or no scope.Therefore, we place the injectors in the appropriate places. Activity injectors in the
AppModule
, fragment injectors in activity modules, and child fragment injectors in (parent) fragment modules.
Running the application shows the main activity, which displays 3 buttons that will (later on) launch the example activities.

6. Creating example 1; an Activity with 1 Fragment. [PR|TAG]
For our first example, we will create an Activity that contains a single fragment. This example is very similar to what we did for our MainActivity
and MainFragment
so I will only explain parts that haven’t already been explained, for the sake brevity. Example1Activity
hosts Example1Fragment
, which is injected with the SingletonUtil
, PerActivityUtil
, and PerFragmentUtil
dependencies. The hash codes of each util object is then shown when the do_something
button is clicked. This will allow us to verify that the scoped dependencies have been provided and injected correctly.
First, start by creating the Example1Fragment
, Example1FragmentModule
, and Example1FragmentSubcomponent
.
The SingletonUtil
, PerActivityUtil
, and PerFragmentUtil
are injected and used in the onDoSomethingClicked()
method, which gets invoked when the do_something
button is clicked. The doSomething()
method of each util object is then used to concatenate the hash codes of the SingletonUtil
, PerActivityUtil
, and PerFragmentUtil
objects as well as the hash codes of the activity and fragment. These hash codes are then displayed in the someText
TextView
.
The Example1FragmentModule
and Example1FragmentComponent
are quite similar to the MainFragmentModule
and MainFragmentComponent
therefore are excluded from this article, for brevity of course.
Note: To reiterate, you can take a look at the [PR] for the complete changeset and checkout the [TAG] for the complete code. This is the last time I reiterate this for the rest of this article 😛
Next, create the Example1Activity
, Example1ActivityModule
, and Example1ActivitySubcomponent
.
The Example1Activity
, simply hosts the Example1Fragment
as seen above.
The Example1ActivityModule
and Example1ActivityComponent
are quite similar to the MainActivityModule
and MainActivityComponent
therefore are excluded from this article, for brevity again.
Next, update the AppModule
to provide the injector for the Example1Activity
.
Running the application’s example 1 shows a “Do Something” button. Clicking the button shows us the hash codes of our util objects, activity, and fragment.

There isn’t much to say here besides the fact that the application works as expected and that the dependency injection worked. The hash code of each of the util object are different, but that’s to be expected since they all belong to different classes. The hash code of the activity and fragment are, of course, different.
Note: Using hash codes to determine the object’s identity and uniqueness is enough for this small example application. As stated by the
Object.hashCode()
javadoc, “as much as is reasonably practical, the hashCode method defined by classObject
does return distinct integers for distinct objects”. However, with enough objects in memory (thousands), there may be some hash codes that clash. See hashcode-uniqueness.
A more interesting example, and one that proves our dependency injection setup works correctly, will be provided in examples 2 and 3 so keep reading!
7. Creating example 2; an Activity with 2 Fragments. [PR|TAG]
For our second example, we will create an Activity that contains 2 fragments. This example is very similar to our previous example. Example2Activity
hosts Example2AFragment
and Example2BFragment
, which are both injected with the SingletonUtil
, PerActivityUtil
, and PerFragmentUtil
dependencies. The hash codes of each util object is then shown when the do_something
button of each fragment is clicked.
First, create the 2 fragments (Example2AFragment
and Example2BFragment
) and their respective module and subcomponent. Then create the activity (Example2Activity
) and its module and subcomponent.

Question: Why not place the Dagger modules and subcomponents in a
di
package? Or put all of them in a package calledinternal/di
?I’ve seen several projects do this, I’ve even done it myself. It makes me question if it is standard practice to do so. In any case, we are not placing all Dagger modules and subcomponents into such a package because then all of the dependencies that have to be provided throughout the application have to be public.
Placing the modules and subcomponents in the same package as the dependencies they inject / provide allows classes to be package-private increasing the modularity of the package. It also makes you strategically think about what classes belong to which package and helps you keep the package focused.
The activity and 2 fragments are quite similar to the activity and fragment in the first example. Other than the class names, a lot of this is copy and paste from the previous example. This is done on purpose for clarity.
Question: Why copy and paste code instead of using a base class to share code? Why not put shared example fragment code in a base class?
Copying and pasting code is only done for this guide to promote clarity by making each example independent from one another. By all means you can take the code and refactor it yourself if you want. This guide only violates the DRY principle for the sake of the reader.
The Example2Activity
hosts Example2AFragment
and Example2BFragment
.
The Example2ActivityModule
provides the injectors for the 2 fragments as well as the concrete implementation of an Activity
as per the contract specified in BaseActivityModule
.
Next, we add the Example2Activity
injector to our AppModule
. This is pretty much the same stuff as in the previous example.
Running the application’s example 2 shows the 2 fragments both of which contain a “Do Something” button. Clicking the buttons shows us the hash codes of our util objects, activity, and fragments.

The SingletonUtil
injected in both fragments are the same (as seen by their hash codes). Both fragments live in the same activity so they both have the same PerActivityUtil
and Activity. Since the 2 fragments are different, their PerFragmentUtil
and Fragment instances are different.
Note: Adding multiple different instances of the same fragment class into the same activity will produce different sets of
@PerFragment
dependencies per fragment instance.
8. Creating example 3; an Activity with 1 Fragment that contains 1 child Fragment. [PR|TAG]
For our third example, we will create an Activity that contains 1 fragment, which contains a child fragment. Example3Activity
hosts Example3ParentFragment
, which hosts Example3ChildFragment
. Both parent and child fragments are injected with the SingletonUtil
, PerActivityUtil
, and PerFragmentUtil
dependencies. Example3ChildFragment
, in addition, is also injected with the PerChildFragmentUtil
dependency. The hash codes of each util object is then shown when the do_something
button of each fragment is clicked.
First, create both the parent and child fragment and their respective modules and subcomponents. Then create the activity and its module and subcomponent.

The activity and 2 fragments are quite similar to the activity and fragment in the previous examples. Other than the class names, a lot of this is copy and paste from the previous example. There are some differences though.
The Example3ParentFragment
adds Example3ChildFragment
as a child fragment.
The Example3ParentFragmentModule
provides the injector for Example3ChildFragment
.
The Example3ChildFragment
is injected with a PerChildFragmentUtil
object.
The Example3ChildFragmentModule
provides its dependencies using the @PerChildFragment
scope.
The Example3ChildFragmentSubcomponent
is annotated with the @PerChildFragment
scope indicating that its modules will only provide dependencies with @PerChildFragment
scope or unscoped dependencies.
The Example3ActivityModule
provides the injector for the Example3ParentFragment
.
The AppModule
, as usual, provides the injector for the activity (Example3Activity
).
Running the application’s example 3 shows the parent and child fragment both of which contain a “Do Something” button. Clicking the buttons shows us the hash codes of our util objects, activity, parent fragment, and child fragment.

Similar to the previous example, the SingletonUtil
injected in both fragments are the same (as seen by their hash codes). Both fragments live in the same activity so they both have the same PerActivityUtil
and Activity hash codes.
The PerFragmentUtil
and Fragment instances are the same because the child fragment lives within the parent fragment. The PerChildFragmentUtil
is only available in the child fragment. The child Fragment has a different hash code than the (parent) Fragment, of course.
At this point, we’ve proven that our setup works!
9. Refactoring the subcomponent setup to use the @
ContributesAndroidInjector annotation. [PR|TAG]
As previously mentioned, our Dagger subcomponents are barebones and are quite repetitive, violating the DRY principle! To fix this, Dagger 2.11 has provided us with the @ContributesAndroidInjector
, which auto generates the @Subcomponent
that we would otherwise have to write ourselves. This allows us to delete all of our subcomponent classes.
Question: Why show usages of
AndroidInjector
,AndroidInjector.Factory
,@Subcomponent
, and@Subcomponent.Builder
at all? Can’t we just use@ContributesAndroidInjector
in all cases?In some cases, we won’t be able to use
@ContributesAndroidInjector
. Such cases include times when you need to bind a component instance using@BindsInstance
as seen below. You will need to use@Subcomponent.Builder
in this case.

Future versions of dagger-android may (probably not) add additional features such as this in
@ContributesAndroidInjector
but as of right now, versions 2.11–2.17 does not support it.Question: Definitively, when can we use
@ContributesAndroidInjector
?This is answered in the small pro-tip in the official dagger-android integration page.

The examples in this article fit the criteria for using
@ContributesAndroidInjector
.
Migrating to @ContributesAndroidInjector
is done in 3 easy steps;
- Replace
AndroidInjector.Factory
usages in all modules with@ContributesAndroidInjector
. - Delete all
subcomponent
inclusions in every module. - Delete all classes annotated with
@Subcomponent
.
There are a lot of (similar) changes to be done here so I will not show every change. I will only show how to refactor example 3 since it uses all of the different scopes. You may review the rest of the changes in the full [PR].
First, replace AndroidInjector.Factory
usages in all modules with @ContributesAndroidInjector
.



Notice how the scopes of the injectors and the modules they include are now provided in the module provides method instead of in a subcomponent class.
Next, delete all subcomponent
inclusions in every module.

Note that only the Example3ActivitySubcomponent
needs to be deleted for this example.


Finally, delete all classes annotated with @Subcomponent
. This part entails deleting the Example3ActivitySubcomponent
, Example3ParentFragmentSubcomponent
, and Example3ChildFragmentSubcomponent
.
Example 3 at this point is no longer using subcomponents! Again, you may review the rest of the changes for the main activity and other examples in the full [PR].
Conclusion
In this part of this 3-part series, we have created a project, from scratch, using the new Dagger.Android (2.11–2.17) dependency injection framework with support for @Singleton
, @PerActivity
, @PerFragment
, and @PerChildFragment
scopes. If you’ve used previous versions of Dagger 2, you should be able to see how much less Dagger code is involved with this new dagger.android setup!
Question: There is a google sample for using dagger-android and MVP. This guide has a different structure than the google sample. Which do I trust / follow?
This is completely up to you. I wrote this guide to show others an architecture using Dagger-android, Butterknife, and MVP. As with anything, there is never one way of doing something. Choose an architecture / structure that meets your needs and one that makes sense to you and one that you are comfortable with. I suggest that you read this guide in its entirety. I did my best in explaining every line of code so that everything makes sense, which is something that the google sample probably doesn’t offer (among other things perhaps).
Read part 2 to see how to replace a lot of handwritten boilerplate view binding code we have created by using ButterKnife (8.7-8.8).
Read part 3 to find out how to restructure our code to Model-View-Presenter (MVP) to increase testability, maintainability, and scalability.