Using Dagger 2 with MVVM SIMPLIFIED!
The word Dagger sounded weird the first time I heard about it as a developer. I avoided it for few months but had to embrace it because of it’s advantages as a Dependency Injection framework in software development. When I got started, I was stuck as I could not get explicit guidelines to setting up Dagger 2. I read many articles and codes with old and new implementations but yet became more confused. Somehow, I found my way through and I would like to share it.
Update
Kindly note that Dagger-Android is deprecated while we now have Dagger in Android which is Dagger2 itself. Hence, the setup in this article might not be needful any longer. Thanks for reading!
Scope
This article encompasses so much about android development but will be limited to just Setting up Dagger 2 framework using MVVM architectural pattern.
If you find it difficult to understand DI or the MVVM architectural pattern, please check out these articles to have clearer understanding on:
- Dependency Injection on Android
- Dagger
- Dagger 2. Part 1. Basic Principles, graph dependencies, scopes
- Dagger 2 Annotations
- Dependency Injection Benefits
- MVVM Architectural Pattern
I developed a trivia quiz app called Triviums which will be used as a sample project in this article.
Please note that some parts of the code will be extracted and will not be different.
Project Configuration
Since Dagger 2 is a library, we need to add it as a dependency in the build.gradle
file:
Project Structure
From the image below, many packages were created to separate modules according to features. For example, we have core
, dagger
, etc.
Setting-up Core Classes
In order to reduce boilerplate and the steps required to create new Activities and Fragments, Dagger provides some base classes called DaggerApplication
,DaggerAppCompatActivity
and DaggerFragment.
These contain applicationInjector, AndroidInjection and AndroidSupportInjection respectively which were supposed to be included in all classes and fragments.
From the Project Pane, we have the following classes:
HorizonMainApplication:
a class which extends the DaggerApplication
class. This is a base class in android that contains all android components such as activities, services, broadcast receivers etc.
BaseActivity:
an abstract class created which extends the DaggerAppCompatActivity
class. Per adventure you have some other methods that would be used in all activities, you could put them in this class while the activities extend it.
BaseFragment:
an abstract class which extends the DaggerFragment
class. Including methods as explained in BaseActivity
also applies here.
Setting-up Dagger 2 Elements
For better grasp, I designed a structure of Dagger 2 as shown below. As we move on, I will explain/quote some terminologies.
This article gave a very concise descriptions of the Dagger 2 elements:
@Inject — base annotation whereby the “dependency is requested”
@Module — classes which methods “provide dependencies”
@Provide — methods inside @Module, which “tell Dagger how we want to build and present a dependency“
@Component — bridge between @Inject and @Module
Now we can proceed to have a look of the code set up:
HorizonMainComponent class
This class combines all the module classes used in the app for compilation by the Dagger 2 library.
HorizonAppModule class
This class contains classes that are accessed or called in any activity/fragment within the app. In other words, not attached to any particular activity/fragment.
ActivityBuilder class
This class houses all Activities and Fragment Modules.
Setting-up to use Dagger 2 in an Activity
In the older implementation of Dagger 2, annotations (such asBinds
ComponentBinds
Subcomponent
ActivityKey
FragmentKey
) were used to scope Application
, User
and Activity
of an app. Like I said earlier, Dagger made it easier and reduced all boilerplate and introduced @ContributesAndroidInjector.
Read Dagger 2: @Binds and @ContributesAndroidInjector for more details.
MainActivity Class
In the snippet below, the commented code was supposed to be included but remember we have our BaseActivity
which extends DaggerAppCompatActivity
.
MainActivityModule class
The @Provides
annotation indicates that we will need the class MainActivityViewModel
within the MainActivity
Activity.
MainActivityViewModel class
The dependency is provided using the @Inject
annotation via the constructor.
Setting-up to use Dagger 2 in a Fragment
The concept described above for the Activity is same for Fragment but there are some slight differences which will be pointed out in this section of the article.
CategoryFragment class
Remember in the HorizonAppModule
class discussed earlier, the Utils
class injected in the code snippet was provided in the module class. Also, the ViewModelProvider
class was injected for use.
CategoryFragmentModule class
This class contains and provides all the methods and/or classes that would be used within the CategoryFragment
class only.
CategoryFragmentProvider class
Since a Fragment can not exist without an Activity, so it is that it can not be injected into the ActivityBuilder
class except being provided indirectly to an Activity with the help of an abstract class called CategoryFragmentProvider.
CategoryViewModel class
Recommendations
Check out the aforementioned references. Also, Android MVVM with Dagger2, Retrofit, RxJava and Android Architecture Components
Conclusion
Uhh! Well done… I believe you can now set up your next project using MVVM architectural pattern with Dagger 2 for DI.
Please feel free to comment and share.
You can find the full source code here: