
A Dependency Injection Showdown
Choosing a dependency framework for your Android app is a big decision, it’s not something that you can easily replace later on. Dependency injection spans all layers of your app so it’s important that the DI framework that you choose meets all your requirements and that includes testing.

I am going to compare 4 popular frameworks: Dagger, Koin, Kodein, and Toothpick. It’s interesting that all of these frameworks also run on the JVM and 2 of the frameworks also integrate with the popular Ktor framework. I am going to demonstrate how to integrate these DI frameworks into a simple application. Although the application will run on Android many of these concepts can be easily applied to non-Android projects.
The application contains a GreetingService
which may either return “Good morning” or “Good evening” depending on the hour of the day.
The TimeService
is used to return the current hour of the day. The GreetingService
will use the TimeService
to determine if it is morning or night and tailor the message accordingly.
The MessageData
is used in the greeting message to add additional text to the message.
As you can see it’s a pretty simple example. I’ll show you how to use each DI framework and more importantly how to test your code. Even if your a non-Android developer you should still be able to understand these examples. Basically, we initialize our DI container when our application starts up using the Application
class and we display our greeting message on the screen in the Activity
class. That’s pretty much all the Android knowledge you need.
Framework Comparison
Before we get started here is a high-level overview of each framework showing the popularity, who supports its and where it runs. Later we’ll dive deeper into how each framework is used and see what the code looks like. As you can see Dagger is by far the most popular framework with 14.8K stars on Github.

Now, let's get started!
Koin
Koin was designed to be a pragmatic lightweight dependency injection framework that doesn’t use code generation, proxies or reflection. Over the last couple of years it has become very popular due to its simplicity.
Koin code
Koin uses the Module
to wire up its dependencies.
Here the DI container is initialized with the Module
declared above.
To display the greeting on the screen we need to inject the GreetingService
and call the service after it is injected.
Koin testing
Koin provides its own mock classes that making testing the GreetingService
really easy so you don’t need another mocking framework.
Performance metrics from the Koin website.

Overall I found it really easy to setup Koin, it has a very nice DSL, good support for Android and I had no trouble with testing the injection.
Good
- Good documentation
- Easy mocking for testing
- Simple & clean DSL
- Supports scopes
- Android & JVM support
- 2nd most popular framework in Android
- Ktor support
Bad
- Kotlin Multi-Platform support (Update Oct 2020 : Coming soon in alpha)
- get() in module
- Slower than the DI frameworks that generate code
- Doesn’t support JSR 330
Kodein
The Kodein framework was designed to provide painless dependency injection in Kotlin projects. It’s one of the first pure Kotlin dependency libraries and supports multiple platforms including iOS, Javascript, Android, and the JVM.
Kodein code
Wiring up the dependencies is pretty similar to Koin. In the Module
you bind the interfaces to the implementations.
The DI container is also initialized with the Module
and started in the Application
. Kodein uses an interface calledKodeinAware
to mark the classes that are used for dependency injection.
The Activity
also needs to use the KodeinAware
interface so the GreetingService
can be injected.
Kodein testing
Kodein provides a nice dependency override feature so you can easily inject fakes into the GreetingService.
It took me a little bit longer to get the Kodein example up and running mainly due to the documentation of the website being out of date. The DSL is similar to Koin but not as clean. I also found it to be a little bit more complicated than Koin.
Good
- Supports Kotlin Multiplatform
- Easy to test with fakes
- Ktor support
- Good Android support
- Simpler than Dagger
Bad
- Documentation not up to date
- instance() in module
- DSL and syntax not as clean as Koin & Toothpick
- More complex than Koin & Toothpick
- Slowest of all 4 frameworks
- JSR 330 support
Dagger
Dagger is a fully optimized dependency framework for Android using generated code to avoid reflection. It is maintained by Google and is their recommended solution for doing DI on Android.
Dagger code
A Dagger Module
is a little bit more verbose than the Modules
used in the other frameworks. It uses annotations to describe the classes and wire up the dependencies as follows;
The constructor of theGreetingServiceImpl
also needs to modified to add the @Inject annotation for Dagger to declare it as a Singleton.
This also needs to be done for the TimeServiceImpl.
Note that you use also need to remove the default message for the MessageData
class otherwise will complain about multiple constructors.
Dagger requires an additional Component
class to specify the Modules
that will be used in your app. You also need to define the methods that will inject your classes and a Factory
to inject the String
into the constructor of the MessageData
class.
The generated class DaggerComponent
is used to start the DI container and is initialized with the Module
.
To display the greeting on the screen you need to retrieve the Dagger Component
from the Application
and inject the Activity
with the GreetingService
.
Dagger testing
I checked the Dagger codelab and the recommendation way to test your classes was with mocks without using Dagger. That’s one of the reasons why Google recommends constructor injection over field injection.
Dagger still requires quite a lot of boilerplate to wire up your dependencies and use it in your app. It will be a welcome relief when Google addresses these issues and simplifies the syntax.(Update Aug 20 : Hilt has been released to address these issues however it’s still in alpha) If you work as a consultant and work on many different apps most likely you will run into Dagger eventually, so it’s one of those frameworks that you have to know anyway.
Good
- JSR 330 support
- Feature-rich
- Good documentation & codelab
- Lots of examples and blog articles
- Most popular DI on Android
- Google support
- Compile-time checking of dependencies
- Fast
- Google working to addressing the bad
- Uses incremental annotation processing
Bad
- Overly complex
- Need to reference generated classes
- Boilerplate
- Can be slow working with your IDE
- No DSL
- Kotlin Multi-Platform support
Toothpick
Toothpick is a scope tree based Dependency Injection (DI) library for Java/Kotlin/Android and maintained by Groupon. It is a full-featured, runtime based, but reflection-free, implementation of JSR 330.
Toothpick code
Toothpick’s DSL is the easiest to read, it also generates factories for instance creation avoiding the need for the ugly method calls such as get() or instance().
For Toothpick to generate these factories you need to add the @InjectConstructor annotation to the class being injected. Alternatively, you can also use the @Inject annotation constructor syntax which was used in the Dagger example.
The Module
is installed in the root scope when the application starts up.
The GreetingService
is injected into the Activity
using the root scope. Once injected the GreetingService
can be used to display the greeting on the screen.
Toothpick testing
The ToothPickRule class allows you to inject the class that you are testing with mocks.
You can also override classes with fakes by installing a test Module
.
Just for completeness, this how you would use Toothpick and Robolectric.
Performance metrics from the Toothpick website.
On an average of 50 runs, the cost of setting up the injection system, i.e creating an injector (RG), a component (Daggers), and a scope (Toothpick) are:
- RoboGuice 4: 105 ms
- Dagger 1: 20 ms
- Dagger 2: 22 ms
- Toothpick: 1 ms

Toothpick’s clean DSL and clear use of scopes makes it easy to understand and use Toothpick on your project. It’s the fastest DI framework around and one of the easiest to test. Although it uses generated classes you don’t have to reference any of these classes.
Good
- JSR 330 support
- Supports both annotations & delegates
- Very good documentation
- Supported by Groupon
- Cleanest DSL compared to Koin & Kodein
- Easy to test
- Fastest of the 4 frameworks
- Uses incremental annotation processing
Bad
- Kotlin Multi-Platform support
- Not many examples & blogs posts about it
Final standings
When I evaluate frameworks usability and testability are always at the top of my list. A framework doesn’t have to be the fastest or be written entirely in Kotlin, as long as the framework provides nice Kotlin extensions and runs at a reasonable speed that is good enough for me. Knowing that the framework is well supported and maintained is also another consideration. Having good documentation is also another must and that’s why some frameworks such as Spring have dominated their domains.
Taking this all into consideration, the winner of this shoot out is Toothpick followed closely by Koin. I feel it would be quite easy for the contributors of Kodein to address the issues I had and also update their documentation. I put Dagger last because in its current form it’s just too complex and verbose to use. It’s good to know that Google is committed to addressing these issues and improving the developer experience. Hopefully in the future it can improve its standing and bring bigger guns to the next shoot out!
1st Toothphick — The winner of this shootout.
2nd Koin — A close second.
3rd Kodein — A decent contender
4th Dagger — Not the fastest shooter out there, it needs fewer bullets not more.
The working code for all the examples including the tests can be found at this repo.
Kotlin Multiplatform & DI
I am really excited about KMP (Kotlin Multiplatform) and hope it lives up to its promises, although it’s still experimental many companies are now using it in production. I have been wondering for a while about how or if DI will be used in a KMP app. I know that many iOS apps don’t use DI and that's why I am wondering if the shared code would still it. At present only Kodein supports KMP and according to Kevin Galligan there is also a forked version of Koin that will support KMP in the future. My prediction is that KMP will disrupt the way we write apps and also the libraries we use, we just have to wait a little bit longer for that to happen.
Thanks to Karl Maul for editing.
Btw, we use both Toothpick and Dagger in our production apps. If you liked this article about dependency injection also check this one out.
If your into KMP check this one out.
https://medium.com/swlh/the-first-step-on-your-kmp-journey-changing-your-microservices-4de3f99f6e56