How to use Dagger? How to configure Dagger to work in my Android project?
I'd like to use Dagger in my Android project, but I find it confusing.
EDIT: Dagger2 is also out since 2015 04 15, and it's even more confusing!
[This question is a "stub" on which I am adding to my answer as I learned more about Dagger1, and learn more about Dagger2. This question is more of a guide rather than a "question".]
Guide for Dagger 1.x:
The steps are the following:
1.) add
Dagger
to thebuild.gradle
file for the dependenciesAlso, add
packaging-option
to prevent an error aboutduplicate APKs
.2.) create an
Injector
class to handle theObjectGraph
.3.) Create a
RootModule
to link your future modules together. Please note that you must includeinjects
to specify every class in which you will use@Inject
annotation, because otherwise Dagger throwsRuntimeException
.4.) In case you have other sub-modules within your modules specified in your Root, create modules for those:
5.) create the leaf modules which receive the dependencies as constructor parameters. In my case, there was no circular dependency, so I don't know if Dagger can resolve that, but I find it unlikely. The constructor parameters must also be provided in a Module by Dagger, if you specify
complete = false
then it can be in other Modules too.6.) Extend
Application
and initialize theInjector
.7.) In your
MainActivity
, call the Injector in theonCreate()
method.8.) Use
@Inject
in yourMainActivity
.If you get the error
no injectable constructor found
, make sure you did not forget the@Provides
annotations.Guide for Dagger 2.x (Revised Edition 6):
The steps are the following:
1.) add
Dagger
to yourbuild.gradle
files:.
.
2.) Create your
AppContextModule
class that provides the dependencies.3.) create the
AppContextComponent
class that provides the interface to get the classes that are injectable.3.1.) This is how you would create a module with an implementation:
Beware:: You need to provide the
@Scope
annotation (like@Singleton
or@ActivityScope
) on the module's@Provides
annotated method to get a scoped provider within your generated component, otherwise it will be unscoped, and you'll get a new instance each time you inject.3.2.) Create an Application-scoped component that specifies what you can inject (this is the same as the
injects={MainActivity.class}
in Dagger 1.x):3.3.) For dependencies that you can create via a constructor yourself and won't want to redefine using a
@Module
(for example, you use build flavors instead to change the type of implementation), you can use@Inject
annotated constructor.Also, if you use
@Inject
constructor, you can use field injection without having to explicitly callcomponent.inject(this)
:These
@Inject
constructor classes are automatically added to the component of the same scope without having to explicitly specify them in a module.A
@Singleton
scoped@Inject
constructor class will be seen in@Singleton
scoped components.3.4.) After you've defined a specific implementation for a given interface, like so:
You'll need to "bind" the specific implementation to the interface with a
@Module
.A short-hand for this since Dagger 2.4 is the following:
4.) create an
Injector
class to handle your application-level component (it replaces the monolithicObjectGraph
)(note:
Rebuild Project
to create theDaggerApplicationComponent
builder class using APT)5.) create your
CustomApplication
class6.) add
CustomApplication
to yourAndroidManifest.xml
.7.) Inject your classes in
MainActivity
8.) Enjoy!
+1.) You can specify
Scope
for your components with which you can create Activity-level scoped components. Subscopes allow you to provide dependencies that you only need only for a given subscope, rather than throughout the whole application. Typically, each Activity gets its own module with this setup. Please note that a scoped provider exists per component, meaning in order to retain the instance for that activity, the component itself must survive configuration change. For example, it could survive throughonRetainCustomNonConfigurationInstance()
, or a Mortar scope.For more info on subscoping, check out the guide by Google. Also please see this site about provision methods and also the component dependencies section) and here.
To create a custom scope, you must specify the scope qualifier annotation:
To create a subscope, you need to specify the scope on your component, and specify
ApplicationComponent
as its dependency. Obviously you need to specify the subscope on the module provider methods too.And
Please note that only one scoped component can be specified as a dependency. Think of it exactly like how multiple inheritance is not supported in Java.
+2.) About
@Subcomponent
: essentially, a scoped@Subcomponent
can replace a component dependency; but rather than using a builder provided by the annotation processor, you would need to use a component factory method.So this:
Becomes this:
And this:
Becomes this:
+3.): Please check other Stack Overflow questions regarding Dagger2 as well, they provide a lot of info. For example, my current Dagger2 structure is specified in this answer.
Thanks
Thank you for the guides at Github, TutsPlus, Joe Steele, Froger MCS and Google.
Also for this step by step migration guide I found after writing this post.
And for scope explanation by Kirill.
Even more information in the official documentation.