Note: This article is a 10 minute fun read. If you prefer a quicker and shorter tutorial, check out the 4 minute version of Even Simpler Dagger 2 Tutorial

I am a dummy, and learning Dagger 2 is stretching my brain! The tutorials I read introduced so many topics at once e.g. Dependency Injection, Provider, Component, Module, Scope… my brain just exploded!

Besides many of the tutorials are based on Java. Kotlin is the way of doing things today. It took me months to digest Dagger 2 and integrate it with Kotlin. So I vowed to myself that when I understand it, I will create something really super simple, like the ABCs of Dagger 2, for those out there like me looking for a basic introduction.

To help me do so, I create what I believe as the world’s simplest Android App with Dagger 2… Just one page, less than 20 lines 😎 (please don’t make another simpler one, let me keep one world record 😝).

Many tutorial shows pages after pages of codes, and linking relationships between classes. My brains hurts… as my stack is shallow 😝

(For the experts, I apologize for the very unconventional way of introducing Dagger 2, as this is really for dummies.)

Let’s go to (very) basic programming (… in Android)

Okay I admit it, I have some knowledge in programming. I know Function, Class, and Member Variables. And I know how to create a simple Hello World Android App with one MainActivity (Hey! you could do that even without typing a single line of code by using Empty Activity template by Android Studio 😁)

To make it fancier, I can change the simple Hello World App to Simple Hello Dagger 2 App. The code is below (I bold the additions I added to the template).

class MainActivity : AppCompatActivity() {



val info = Info()



override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)



text_view.text = info.text



}

}



class Info {

val text = "Hello Dagger 2"

}

Sorry, I made a simple thing slightly harder than it needs to be by using a class to store my text. And I made a member variable name info to store it. This is important to explain the use of Dagger 2 later.

All very simple so far, I hope.

Moving Info out of Activity…

In a real app, I am not likely to only have a single member variable info . There may be others. Or perhaps I would like to share the same info across multiple activities.

To make this better, instead of creating info in MainActivity class, I want my info (and all other member variables) to be created somewhere else and sent in. Hey, you know what? there’s a term for this… It is called Dependency Injection 😉.

That sounds really simple… maybe I could do as below?

class MainActivity(val info:Info) : AppCompatActivity()

Oops! Android doesn’t allow me to simply add any argument to its Activity’s constructor 🙁. If I want, I have to do the hard way. Refers to StackOverflow. Even if I don’t mind the hard way, this is also almost impossible, as this is the first Activity of my App, who will send it through?

If you have more experience in Android development, perhaps you could think of using the Application to help you… Spot on, you are right! But I am the storyteller here. I am here to talk about Dagger 2, let’s get back to the topic…

Based on a true story…

With that need, people start imagining how nice it would be if we could magically have all dependencies injected (in my case, the dependency is info ). For Android, the imagination gave birth to Dagger, by this group of most admirable experts working at Square. Google admires their work so much, they made the second version of it called Dagger 2.

It’s popularity is so great… until one day a dummy also like to learn about it… and decided to create a blog …. Okay, enough history…

Making Info appear magically?

With Dagger 2 created, one could now make Info magically appears. The most magical thing is to totally remove the line val info = Info() , but this is TOO magical. It is beyond Dagger 2 capability, might need David Copperfield.

So to be more realistic, we still have to tell MainActivity to have the info member variable, but it DOES NOT need to create/initialize it (i.e. leave that to happen magically).

In Kotlin, because we want info as a non-nullable item, it has to be initialized with something. But since we don’t know what it will be initialized to while waiting for the magic from Dagger 2, we will need to inform Kotlin to worry about that later by adding a lateinit modifier to it.

So in short, just add lateinit var info: Info to replace the previously removed line.

class MainActivity : AppCompatActivity() {



lateinit var info: Info override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)



text_view.text = info.text



}

}



class Info {

val text = "Hello Dagger 2"

}

Hey, don’t compile and run the above code, it will CRASH 💥! It is simply because info has not yet be initialized.

Sorry no magic yet. Don’t get mad at me… This is not a trick. I promise we will not need to initialize it in MainActivity. We’ll let Dagger 2 to do it for you

Now, into the real Dagger 2 world…

Adding Dagger 2 libraries

But before that, some mundane stuff. Anything you need beyond basic Android stuff, you’ll have to manually add the libraries to your project. Dagger 2 is no different. Just follow the step below

In your app’s build.gradle file, (note: not project’s build.gradle ), add the bold lines as following

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-kapt'

And

dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])

// ... other dependencies ...

implementation 'com.google.dagger:dagger:2.13'

kapt 'com.google.dagger:dagger-compiler:2.13'

}

Then sync your project. You now have Gun 2 with you… Ops, I mean Dagger 2.

Back to real code… Introducing @Component

Let’s get back to the actual code. Now let me introduce you to a little thing call @Component . It’s a way for me to tell Dagger 2, “Hey! I want a little magic box that does the magic instantiating my member variable”

I declare my magic box like this (as an interface)

@Component

interface MagicBox

I call it MagicBox just to make it different from other tutorials, so you know you could name it anything. Other tutorials will call it <Something>Component . In a group project I recommend follow this convention, so everyone could understand your code

I also need to tell my magic box that it is there to perform its magic on MainActivity. So to do that, I create a poke function accepting MainActivity in my MagicBox .

@Component

interface MagicBox {

fun poke(app: MainActivity)

}

Note I use poke just to make it different from other tutorial, so you know you could name it anything. Almost every other example I see, people call it inject . In a group project I recommend follow this convention, so everyone could understand your code.

Now, to make things a little clearer how they are related, you could imagine that MagicBox would be used to Poke MainActivity as diagram below, and provide the info to MainActivity . We just need to put info into the MagicBox , then the magic shows will be done! … I’ll show you how info is inserted into MagicBox in a short while…

Before showing how info is place in the MagicBox , let’s use some imagination here. This is in case you are wondering why the trouble of making MagicBox while we could just have info created directly in MainActivity .

Assuming we have a lot of other members variable other than info , and we also have other activities and classes that need them. So the diagram will be as below, and the MagicBox handle all the poking happily, without any activities or classes worry about initiating their own member variables.

👏👏👏, MagicBox handles all these for us! How nice…

Okay, let’s get back to the reality of the single info and one MainActivity , since we want to create the world’s simplest Android App with Dagger 2.

Putting `Info` into @Component… Intro to @Inject

Okay, now let’s put info into @Component .

I guess you must be thinking if we have to manually put info into @Component , then what’s so special about @Component . Can’t we create a class to do just that? That’s no magic at all!

Wait… The Dagger 2 magic is coming soon… By soon, I mean NOW.

The magic is that I don’t need to put info into MagicBox . All I need to do is add some special magic keyword (or better known as annotation) to my Info class, and Dagger 2 will be able to know where to get it.

Let me introduce to you… Mr. @Inject !

Change the little Info class from

class Info {

val text = "Hello Dagger 2"

}

to

class Info @Inject constructor() {

val text = "Hello Dagger 2"

}

Sorry you need to add a little more than just @Inject , as we omit the constructor in the earlier code. Since the @Inject needs to be added on the constructor, we need to resurface the Kotlin constructor through the constructor() function above.

With the @Inject annotation in place, Dagger 2 would then smart enough to get the Info class instantiated as needed through the MagicBox . It’s so easy, that you could add @Inject to almost any existing class, and the class object would be hooked up to the MagicBox magically for its creation as needed.

If you wonder how… That’s the magic Dagger 2 does under the hood. So let’s don’t worry about it, since we are just dummies 😝.

Building the MagicBox… Another Dagger 2’s magic

It is not all over yet. We have define the MagicBox , and also have easily hook up Info to our MagicBox. We also have a poke function in MagicBox that we could use to poke MainActivity .

Up till now, we haven’t poke it yet!

Before we can do any poking, we need to Build the MagicBox …

But MagicBox is an Interface. Who wants to implement the detail of it?

Fear not! That’s more magic from Dagger 2. Since you have named it MagicBox , all you need to do is acknowledge Dagger 2 is the Lord over the MagicBox by calling a new magically created Static Class name DaggerMagicBox .

This Static Class will provide you the Builder to build MagicBox . To build it you just need to call

DaggerMagicBox.create()

Don’t worry if Android Studio complaints they don’t recognize DaggerMagicBox , it is not created yet at that time. Just trust Lord Dagger 2, and he shall provide. Click Compile/Run… it will be as promised, magically created during compilation, and you will have it!!

Now you can poke

Okay, the poking of MainActivity could be done by adding the below code in bold. (i.e. create the magicBox , and call the poke function from there. Sending in MainActivity by using this )

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

DaggerMagicBox.create().poke(this)

text_view.text = info.text

}

Ideally after this step, it all should work.

Compile… run… CRASH 💥! It complains the same thing, info is not initialized yet!

Please please, don’t shoot me… I didn’t lie about the magic of Dagger 2. Just allow me one more step below… I promise the last one…

@Inject again!!

In MainActivity, we have info defined as below

lateinit var info: Info

Dagger 2 doesn’t want to hijack any member variable by creating them without having my permission. This is good, as I might want to have my own Info sometimes.

So to inform Dagger 2 which member variable I want it to create magically, just use the same magic word i.e. @Inject , by putting in front of the member variable.

@Inject lateinit var info: Info

DONE! That’s all. Compile, works!

World’s simplest Android App with Dagger 2 code

With that, all the codes shared is as below, all in a file (less than 20 lines in total, and only 4 lines of Dagger 2 related codes in bold)

class MainActivity : AppCompatActivity() {



@Inject lateinit var info: Info



override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

DaggerMagicBox.create().poke(this)

text_view.text = info.text

}

}



class Info @Inject constructor() {

val text = "Hello Dagger 2"

}



@Component

interface MagicBox {

fun poke(app: MainActivity)

}

You can get the entire project from

My hope is the single-page code would help one to easily link up all the essential pieces of working with Dagger 2.

Is this the end of the show?

No, definitely not. This is just the tip of the iceberg of Dagger 2. But I think for a dummy like me, digesting this simple piece is a good start, and my brain needs to rest a bit to continue.

I know what I shared is basic (and I hear some of you complaining and saying this is an injustice to Dagger 2. Sorry… I’ll catch up to that later if the reader likes to hear more), and I purposely left out some other also important elements such as @Module, @Singleton, @Scope, etc. They are not here so I could minimize as much, make it more bearable to a total newbie. But they play important roles to make Dagger 2 of great use.

So I have written the next one as linked below if you like to continue reading.

Optionally, you could also search for other tutorials, as I believe this one would have give you a good basic grasp of how things are connected. With it you might be ready to read the more solid tutorial from elsewhere.