During Google I/O, Google introduced architecture components which includes LiveData and ViewModel which facilitates developing Android app using MVVM pattern.

In the first article of this series, we discussed how can these components serve an android app that follows MVVM. In this second article, we will answer one of the questions that was raised at the end of the first article which is Dependency injection.

This article assumes that you have a basic knowledge of Dagger since we will focus on setting up the latest Dagger version (version 2.11) in our MVVM sample in order to implement Dependency injection.

If you need basic information about Dagger 2.11, checkout Dagger user guide.

Configuring Dagger 2.11

First of all, let’s add Dagger 2.11 dependencies to our MVVM Sample.

Specify Dagger Version 2.11

Including Dagger core

Including Dagger Android

Dagger 2.11 Project Setup

The following figure shows the main Dagger 2.11 setup that we have in this sample.

Dagger 2.11 setup in MVVM Sample

We have mainly the following Dagger App classes/interfaces:

1. AppModule is a Dagger module responsible for providing singleton services on the application level such as GitHubService and ProjectViewModelFactory.

2. AppComponent is responsible for injecting AppModule.

3. ViewModelSubComponent is a sub component to create View Model instances.

4. MainActivityModule and FragmentBuildersModule are activity and fragment instances providers.

5. Injectable is just a marker interface for fragments that will be injectable.

6. AppInjector is a helper class to automatically inject fragments if they implement Injectable interface.

Now, let’s get into the details of every Dagger item in this setup.

Creating View Model SubComponent

The following code snippet shows ViewModelSubComponent interface, which is responsible for creating ViewModel instances.

Note that, ViewModelSubComponent will be called by ProjectViewModelFactory for getting ViewModel instances.

But what is ProjectViewModelFactory?

The next section answers this question.

Creating custom View Model Factory

ProjectViewModelFactory is a factory that extends ViewModelProvider.Factory in order to provide ViewModel instances to consumer fragment classes.

The following code snippet shows ProjectViewModelFactory which is a self-explanatory Factory implementation that extends ViewModelProvider.Factory.

Now, let’s see the main app module in the next section.

Creating App Module

AppModule is a Dagger module responsible for providing singleton services on the application level such as GitHubService and ProjectViewModelFactory to consumers. The following code snippet shows AppModule class.

Something important here to note, do not forget to wire ViewModelSubComponent to AppModule by specifying it in the subcomponents parameter of @Module annotation.

Creating Injectable and AppInjector

Injectable interface is just a plain empty marker interface as follows.

Injectable will be implemented by fragments which will be injectable.

In order to automatically inject fragments if they implement Injectable interface, the following AppInjector helper class is created to inject fragment instance on onFragmentCreated() as follows.

One thing to note, AppInjector.init() will be called in App startup (as what we will show in Custom Application class section).

Creating Activity and Fragment Modules

The following code snippets shows Fragments Dagger module.

Starting from Dagger 2.10, @ContributesAndroidInjector easily attaches activities and fragments to dagger graph. The following code snippet shows MainActivityModule.

Now, let’s look into the last item in our Dagger 2.11 setup, which is, AppComponent.

Creating AppComponent

The next code snippet shows AppComponent interface.

One thing important to note here, adding to including AppModule and MainActivityModule, we added AndroidSupportInjectionModule to AppComponent as per the official documentation that states that it is necessary in order to ensure that all necessary bindings are available. AndroidSupportInjectionModule is a built-in module in dagger-android:

https://github.com/google/dagger/blob/master/java/dagger/android/support/AndroidSupportInjectionModule.java

Updating Repository Layer Implementation

Now, we are done from setting up Dagger 2.11, let’s update our existing app code in order to utilize Dagger dependency injection.

ProjectRepository will not have to create GitHubService service instance manually anymore, all what it needs to do is to use @Inject in its constructor for GitHubService instance as shown below.

Updating ViewModel Layer Implementation

Updating ViewModel layer is also necessary to avoid creating an instance from ProjectRepository manually inside this layer.

The following code snippet shows an example from ProjectViewModel which uses @inject annotation to have both Application and ProjectRepository instances injected.

Updating View Implementation (Fragments and Main Activity)

Updating View layer is also necessary to avoid creating instances from ViewModel classes manually inside this layer.

The following code snippet shows an example from ProjectFragment.

Some important points to note here:

1. Every fragment now must implement Injectable Interface.

2. Fragment classes should refer to ViewModelProvider.Factory in order to get ViewModel instances.

Creating Custom Application class

Finally, our custom application class code is shown below.

Two main things to note here:

1. Application class has to implement HasActivityInjector, and @Inject a DispatchingAndroidInjector<Activity> to return from the activityInjector() method.

2. In the onCreate() of Application class, we initialize AppInjector in order to automatically inject fragments if they implement Injectable interface.

Source Code

Checkout the source code of the updated app in GitHub, feel free to fork and update as you wish:

https://github.com/hazems/mvvm-sample-app/tree/part2

What is Next

After this article, you now have enough information to create your own MVVM app using Google Architectural components. Hopefully, I will have a room for the next articles in this series that will cover the following topics:

1. Error Handling.

2. Adding more functionality to this demo to see how can Room facilitates SQLite Data operations, and how to implement effective caching.

3. Unit Testing.

4. Where can we use Rx with this architecture?

5. How can we simplify this implementation using Kotlin? (the journey is really having a lot of interesting stuff ;)).

If you like this article, I appreciate your support to share this article with others to let the great Android community know.