Dependency Injection is a concept that did not immediately sound intuitive to my mind, especially as a non-native English speaker. I’ve read a bunch of different articles and resources about it, and found two that helped.
First, Dependency Injection Demystified. The article is quite short and I highly recommend going through it:
Dependency injection means giving an object its instance variables. Really. That’s it.
To understand what “dependency” means, here’s the famous graph about Android’s recommended app architecture:

The arrows in the graph there are the dependencies. So Room depends on SQLite, the Repository depends on the Model, the ViewModel depends on the Repository, and the Activity/Fragment depends on the ViewModel.
The simplest form of dependency injection is like the primary constructor with parameter in Kotlin, like the following example:
class Person constructor(favoriteBook: Book) { /*...*/ }
Here, favoriteBook
is the dependency, while the constructor parameter is the way to inject it into the Person
object. This is in contrast with having the favoriteBook
object created within the class.
The next question in my mind was, why do we need this?
This StackOverflow answer was the second resource that helped me with these two reasons:
Two important ones are the ability to control functionality from a central place (the
Main()
function) instead of spreading it throughout your program…
I think this is pretty obvious.
…and the ability to more easily test each class in isolation (because you can pass mocks or other faked objects into its constructor instead of a real value).
For testing purposes, it’s good if we can test the Person
class individually and send dummy object to it (the favoriteBook
object on the example above). Or, as the official manual dependency injection guide mentioned:
Dependency injection helps make these connections and enables you to swap out implementations for testing. For example, when testing a
ViewModel
that depends on a repository, you can pass different implementations ofRepository
with either fakes or mocks to test the different cases.
And the final question: if dependency injection is this simple, why are there complex tools made for it?
This is turns out relates to the first reason above:
The drawback, of course, is that you now have one mega-function that knows about all the classes used by your program. That’s what DI frameworks can help with.
Once a codebase gets really big and complex, it’s easy to imagine that manual dependency injections can go all over the place. The tools/frameworks eventually are meant to help with that.
3 replies on “Beginner Series: Dependency Injection”
[…] (D.I.) di blog ini. Masih yang basic-basic saja, pertama soal memahami Dagger dan kedua soal cara sederhana memahami D.I dan mengapa dia dibutuhkan. Berita terbaru, ada library baru dari Google untuk membantu mempermudah mengaplikasikan D.I. di […]
[…] a couple of times on this blog. First about understanding Dagger (in Indonesian) and second about a simple way to understand D.I. and why it is needed. The latest development is that Google is now recommending a new library for implementing D.I. […]
[…] This required me to modify the actual class, and when I was done I just realized what this is about. It’s dependency injection! […]