DI 101 — Part 2

Dependency Injection for the Android platform

In the previous article of the series, we discovered that we can use Dagger 2 to inject dependencies in our code, so that it’s not up to us to generate this tree of relations. And now what are we going to see? Soooo many expectations!

Multiple modules

Creating a Retrofit module

We saw that we can have a single module providing us with the different dependencies of the Context, such as ConnectivityManager or SharedPreferences, but we could add something else that would semantically belong to the Context domain, such as an API service.

Let’s imagine that we have Retrofit 2 for interacting with a remote REST service and we want to create a module that provides us with all the dependencies.

First of all, we want to declare a new ApiModule that will provide a Retrofit instance based on a String URL and an OKHttpClient:

At this point, we need only the base URL and the client and, as we saw previously, we can easily create some methods that provide them and Dagger will automatically visit the dependency graph and provide the components we need:

And the same thing goes for the HttpLoggingInterceptor we need in order to log all the network calls the adapter is making:

Adding the module to the component

We saw that we can link modules to components by adding them within the component annotation:

And it is actually what we need to do in order to add a second module:

At this point, we just need to rebuild the project and add this new module to the DaggerApplicationComponent we previously declared in our App.java class. So, from this:

We get to this, by calling the apiModule() method from the DaggerApplicationComponent builder:

Now, we can inject the Retrofit object where we need, it’s just as simple as that!

Providing the Context

But what would happen if we needed the Context? As an example, we could use Realm so let’s try and create a new module that will provide a Realm instance as a singleton:

We add the DatabaseModule.class definition on top of the component as we just did and now it’s the turn of the effective declaration:

We would have expected to declare the Context as constructor parameter for the DatabaseModule (as we do need it), but we did not! That’s because of Dagger 2: it understands that in our component there is already something providing such an object and it visits the graph, calling the providesContext() method of the ApplicationModule automatically. How cool is that!

What about multiple objects?

Providing two different Retrofit

It’s not that uncommon that we need two different objects of the same type, (name it two Strings): how would Dagger 2 understand which provides when, as we could only say that we want a specific String? For this very reason there is an annotation that, with the help of a key, will let us specify exactly what String to provide and when.

Let’s see an example: we need a second Retrofit object pointing to another endpoint but that behaves in the same way of the previous one (so that what changes is actually just the URL). We then create another method that returns a String and we will annotate both this and the previous one with a key:

At this point, we can request which String we want by simply adding the key to the parameter list, so that Dagger 2 knows what to provide:

Of course, we annotate the Retrofit method as well, so that we can identify which client we want easily.

Conclusion

After a first basic example, we are exploring the features that Dagger 2 gives us and it should start to be clear how powerful it can be this framework so… stay tuned for scenes from the next episodes!