- How Dagger, Hilt and Koin Differ Under the Hood?
- Paulina Sadowska
- The Nuggets translation Project
- Permanent link to this article: github.com/xitu/gold-m…
- Translator: keepmovingljzy
- Proofread by: Kimhooo, Mingron
What is the essential difference between Dagger, Hilt and Koin?
Dagger and Koin are undoubtedly the two most popular dependency injection frameworks in Android. The two libraries serve the same purpose and look very similar, but they work very differently underneath.
So what is a Hilt? Hilt is a library that uses Dagger internally, just simplifying its usage, so what I say here about Dagger also applies to Hilt.
In this article, I won’t tell you which library to choose. Instead, I want to show you the essential differences and how those differences affect your application.
Dagger
If we want to provide an instance of a class with a Dagger, all we need to do is add the @Inject annotation to the constructor.
Once this annotation is added, the Dagger generates a Factory for the class at build time. In this use case, since its class name is CompositeAdapter, it generates a class called CompositeAdapter**_**Factory.
This class contains all the information needed to create instances of the CompositeAdapter class.
As you can see, the factory class implements GET () and returns a new CompositeAdapter instance. This is actually the method specified in the Provider \
interface of such an implementation. Other classes can use the Provider \
interface to get an instance of a class.
What if we replace Dagger with Hilt?
In this case, there is no difference. Hilt is a library that uses Dagger internally, and the class I’m showing you is generated by Dagger. If you use Hilt, it does generate some additional classes for us that simplify the Dagger usage and reduce the amount of boilerplate code we need to write. But the core remains the same.
Koin
Koin manages dependencies in a completely different way than Dagger and Hilt. To register dependencies in Koin, we don’t use any annotations because Koin doesn’t generate any code. Instead, we must provide factories for modules that will be used to create instances of each class required in the project.
Koin adds references to these factory classes to the InstancesRegistry class, which contains references to all the factories we wrote.
The key in the map is the full name of the class or the name provided when using the named parameter. The corresponding value is the factory we wrote that will be used to create instances of the class.
To get dependencies, we need to lazily load GET () by calling get() (such as in a factory class) or by calling the Inject () delegate property in Activities or fragments. The get() method looks for the class registration factory for the given type and injects it.
What’s the impact?
Dagger generates code to provide dependencies whereas Koin does not, which actually has some impact.
1. Error handling
Since Dagger is a compile-time dependency injection framework, if we forget to provide some dependencies, we will know of our error almost immediately as our project will fail to build.
For example, if we forget to add the @Inject annotation to the Constructor’s CompositeAdapter and try to Inject it into the Fragment, the build will fail and display the appropriate error telling us exactly what went wrong.
Things are different in Koin because it doesn’t generate any code. If we forget to add a factory for the CompositeAdapter class, the application will build successfully, but will throw a RuntimeException once we request an instance of the class. It can happen when the application starts, so we might notice it right away, but it can also happen later on other screens or when the user performs certain actions.
2. Impact on build time
The advantage of Koin not generating any code is that it has a much smaller impact on our build time. The Dagger requires an annotation handler to scan the code and generate the appropriate class. This may take some time and may slow down our build.
3. Impact on runtime performance
On the other hand, because Koin resolves dependencies at run time, its run time performance is slightly worse.
How much is the difference? To estimate performance differences we can use this library, where Rafa Vazquez measured and compared the two libraries on different devices. The test data is written in a way that simulates multiple levels of delivery dependencies, so it’s not just a virtual application with four classes.
As you can see, Dagger has little impact on startup performance. In Koin, on the other hand, we can see that it takes a lot of time. Injecting a dependency in Dagger is also faster than in Koin.
conclusion
As I said at the beginning of this article, my goal here is not to tell you which library to use. I use Koin and Dagger in two different large projects. Honestly, I don’t think it matters whether you choose Dagger or Koin, what matters is that you can write clean, simple code that is easy to unit test. I think all the libraries: Koin, Dagger and Hilt do this.
All of these libraries have their advantages, and I hope that understanding how they work at the bottom will help you decide for yourself which library is best for your application.
If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.
The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.