What is Dependency Injection and why is it important?

Dependency injection is defined as a design pattern that consists on decoupling the creation of dependencies and their use. In other words, the dependencies that your classes need are created and injected from outside.

We understand as a dependency any piece of logic that our class depends on. For example, if we are writing a class in which we write the business logic related to saving/loading data from a database, we may need to use an object that represents this database.

If you are new to Android and/or to dependency injection, you may be wondering why do we need to do that. At the end of the day, we are adding more “complexity” to our code when you could just create the instances you need just in the moment you need them, right?

And that’s completely understandable. I remember when I started my career as an Android developer, I was finding all this design patterns in the apps I got to work on and I was constantly wondering why did we need all this?

In this article, I will try to explain why all these patterns are actually important and specially dependency injection, which is the main topic of this article.

Why do we need dependency injection?

From a beginner’s perspective, it’s difficult sometimes to see value of certain design patterns like dependency injection. The reason is that probably the only projects you have worked on are mainly small apps that you may have tried to build yourself, or following a codelab, assignments from a bootcamp you followed or some project from your formal studies.

Design patterns are basically generic solutions that solve common problems. In this case, dependency injection solves the following issues:

  • Consistency: As with any design pattern, dependency injection offers a common way of creating and injecting dependencies. That is specially useful when you are working on big projects with teams of 5+ developers, in which the lack of a common solution would make the code a mess and difficult to understand.
  • Testability: As all your dependencies are coming from outside of the class (normally injected through your constructor if you use Dagger, Hilt or similar), you can have more control of the different test scenarios by mocking the dependencies and overriding their functionality with libraries like mockito, specially if the dependencies use some class coming from the Android framework (and you don’t want to use robolectric) or relies on some external source like a database or the network.
  • Scalability: As there are specific classes that are responsible for the creation and injection of your dependencies (depending on the rules that the library you use for dependency injection), you can add more classes that need those dependencies without having to rewrite again how they are created, which allows you to move faster.
  • Separation of concerns: By decoupling the logic of dependency creation from its usage, you are contributing to make your code more easy to maintain.

A few dependency injection libraries you can use on Android

If you want to use dependency injection on Android, you have two options: you implement dependency injection yourself, which can be really time-consuming (and difficult to do even for medium-advanced developers) or you can use one of the libraries available for you.

Without entering into much details, we will list just a few of them with a brief explanation.

Dagger

Dagger is one of the most popular libraries for dependency injection, at least inside the Android community. It is hard to find a developer that has never heard about it. Dagger doesn’t limit itself to Android as it has no dependency to the Android framework. Instead, it can be used in any project written in Java (or Kotlin).

Something important to know about Dagger is that Dagger has two versions, 1 and 2. Even if the two versions have some similarities, the 2 second version has almost completely replaced Dagger 1 except for some exceptional rare cases of apps that may have not migrated yet since the version 2 came out in 2016.

You can learn more about Dagger in their official website.

Hilt

Hilt (also known as Dagger Hilt), it’s a library built on top of Dagger, which basically helps you to implement Dagger reducing the boilerplate needed. One of the main differences with Dagger is that Hilt is only meant to be used on Android projects, as it mostly provides annotations to implement in your Activities, Fragments and Application, etc, which are all part of the Android framework.

You can learn more about Hilt in the Android developers official website.

Koin

Koin is another framework for dependency injection written in Kotlin. A big difference with Hilt and Dagger is that it can be used for Kotlin Multiplatform Mobile, an SDK that allows you to share some common logic between Android and iOS.

You can learn more about Koin in their official website.

Conclusions

In this article we tried to explain what is dependency injection and why it is important, trying to highlight the main benefits of this design pattern. At the end, we also exposed some libraries that you can use to implement dependency injection on your Android projects.

I hope that this article helped understand the benefits of dependency injection and why you should use it, specially when you work in big projects with multiple developers.

In the future, we will write articles explaining some of the most known dependency injection frameworks mentioned in this article. If you are interested, please keep reading!

Leave a Reply

Your email address will not be published.