Dagger 2 for Android Beginners — Advanced part II
This story is the seventh part of the series, Dagger 2 for Android Beginners. If you did not read the previous one, you can start from below.
Series Pitstops
- Dagger 2 for Android Beginners — Introduction
- Dagger 2 for Android Beginners — DI part I
- Dagger 2 for Android Beginners — DI part II
- Dagger 2 for Android Beginners — Dagger 2 part I
- Dagger 2 for Android Beginners — Dagger 2 part II
- Dagger 2 for Android Beginners — Dagger 2 Advanced part I
- Dagger 2 for Android Beginners — Dagger 2 Advanced part II(you’re here)
Previously on Dagger 2..
We took a sample kickstarter project and attempted to decouple and inject the dependencies using Dagger 2 APIs and annotations.
We also saw 3 new annotations. One is @Scope
— which is used to get singleton dependencies. Next is @Named
— which is used to differentiate dependency providers. Another one is the@Qualifier
annotation, an alternate to @Named
annotation and we saw the implementation of both.
Creating multiple Components
Till last pit stop, we created Application
level dependencies. But what if we need some dependencies at the Activity
level? Since Activity
creates and destroys in its own lifecycle, how about its dependencies as well? So, dependencies created within Activity
should be destroyed with Activity
itself.
The best practice here is, when you’re injecting dependencies into clients who have different lifecycle from where dependencies are coming, it’s better to create a separate module and component for them.
In this example, I did not want to add additional features to explain this. Instead, let’s consider our MainActivity
as a separate feature and let’s create separate module and component for it.
For the following changes, refer the branch Dagger2Part2
Step 1: Creating Activity level scope
For the upcoming changes, in the branch above, I have packaged all the new files under MainActivityFeature
.
We have to create a new Scope for our MainActivity.
Step 2: Creating Component for MainActivity
Now, let’s create a separate Component for MainActivity
with MainActivityScope
.
As you notice in the gist, we need to make our MainActivityComponent
talk to our RandomUserComponent
. So, we’ve used the attribute dependencies
to make it talk to it. In other words, it tells dagger that if you need additional dependencies for this component, look at RandomUserComponent
.
For the Activity level, for our example, we need the adapter and the API call as the dependencies. Hence the methods getRandomUserAdapter()
and getRandomUserService()
.
Step 3: Creating MainActivity Module
Let’s now create a module for MainActivity, which provides the adapter dependency.
Note: Injecting MainActivity
through the adapter is not necessary. Just for the example, I’m doing it. If you need Context
for Picasso
, you can use holder.imageView.getContext()
.
Notice the scope @MainActivityScope
that we’ve added to randomUserAdapter()
method — to limit the scope within the Activity
.
We also need to map this module to its corresponding Component MainActivityComponent
— modules = MainActivityModule.class
Step 4: Creating Application Class
This Application
class holds all the application level dependencies — RandomUserApplicationComponent
.
Step 5: Modifying MainActivity
If you would have hit the build button, Dagger would have created DaggerMainActivityComponent
for us. Using this, in our MainActivity
, we need to get Activity level dependencies — adapter and API service.
Note: In the branch, look for the method afterActivityLevelComponent()
Step 6: Congratulate yourself
Yes. we’ve somewhat established some manageable code. We have created activity level dependencies. Congratulate yourself :-)
What if we have 50 dependencies in our Component?
So, the question is what if if we have more dependencies? do we need to write same statements like below all the time?
randomUserApi = mainActivityComponent.getRandomUserService();
mAdapter = mainActivityComponent.getRandomUserAdapter();
….
You might think that you don’t care as well. But I know someone who can shorten it for you. Yes. it’s @Inject
annotation!
Using @Inject annotation
Instead of telling Dagger that you want RandomUserService and RandomUserAdapter, let Dagger react upon the field with @Inject annotations.
By little modification as below, we’ll be able to use @Inject
in no time. Please refer the following branch InjectMainActivity
Modifying MainActivityComponent
Remove the methods getRandomUserService()
and getRandomUserAdapter()
and add the method to inject MainActivity
.
Modifying MainActivity
How does this work? well, when Dagger finds the void method — no return type, it knows that there must be something that it needs in the class i.e. the fields annotated @Inject
and it will initialise them.
Yes! that’s it. Now you can run the code!
TL;DR
We saw an example on creating and injecting dependencies at the activity level. In other words, creating and interacting components when the client has its own lifecycle.
We also saw an example of using @Inject
annotation to inject MainActivity.
Closing note
Thank you for taking your time to read and support the entire series. I hope you have at-least gained some insights about Dependencies and Dagger 2. The reason I wrote this series is that, I gained knowledge about Dagger 2 by reading many blogs but I gained even more insights when I explained it back to you (writing blogs). So I encourage all the readers to share the knowledge back in any way possible. I’m not an expert in Dagger 2, I consider myself a learner. So, if you have found any better way to explain this or any alternate approach, please do write a post and tag this series.
Feedback
If you have found any faults or if the explanation is not clear or a better approach, please write to me to hariutd@gmail.com.
I encourage feedback and it’s the quick way to learn and reiterate myself.
What’s Next?
Well, this is the last part of the series. If I come across other resources, I will definitely write about it.
You can now check other resources and I hope you will understand that content — as you would have gained the foundation in this series.
References and other resources
- https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b
- https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd
- https://blog.mindorks.com/the-new-dagger-2-android-injector-cbe7d55afa6a
- https://blog.mindorks.com/android-dagger2-critical-things-to-know-before-you-implement-275663aecc3e
- https://blog.mindorks.com/a-complete-guide-to-learn-dagger-2-b4c7a570d99c
- http://www.vogella.com/tutorials/Dagger/article.html
- https://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe