Hilt vs Koin

Yigitkaantonkaz
IBTech
Published in
4 min readDec 25, 2023

By the definition, While Hilt is a dependency injection(DI) library recommended by Jetpack which is built on Dagger In, Koin is a lightweight DI framework for Kotlin applications. However, in order to understand the Hilt and Koin, we need to first cover the dependency injection concept.

What is Dependency Injection in Android?

Dependency injection (DI) is a crucial aspect of modern Android app development that enabling cleaner code architecture, easier testing, and improved maintainability. For instance,

Instead of this code,

class WeatherService {
fun getWeather(): String{
return "Sunny"
}
}

class WeatherViewModel() {
private val weatherService = WeatherService()
}

We can use it like this with Dependency injection,

class WeatherService {
fun getWeather(): String{
return "Sunny"
}
}

class WeatherViewModel(private val weatherService: WeatherService) {

}

Koin and Hilt are the two popular options for it, each with its own set of advantages and use cases.

Even though their purposes are the same and they work very similar to each other, there are several differences between them. Today, I will try to talk about them as much as I can.

Let’s start by talking about Koin first.

Koin stands out for its simplicity and flexibility. It is a simple DI framework that does not require annotations or code generation. Instead, it makes use of the Domain Specific Language (DSL) provided by Kotlin to specify dependencies and modules.

Koin’s ease of use is one of its benefits. Its minimum setup requirements and its ability to create dependencies with a clear, readable syntax are the aspects that make it stand out. Therefore, Koin is easy for developers who are new to DI.

On the other hand, this features of Koin might come with trade-offs in certain scenarios. Its runtime resolution might lead to potential issues during compile-time if dependencies are not properly configured. Additionally, Koin might not offer the same level of performance optimizations that some other DI frameworks, like Hilt, provide.

But How is the usage of Koin?

First of all, we need to add dependencies to our project’s build.gradle file,

dependencies {
// Koin core features
implementation 'org.koin:koin-core:3.2.0'

// Koin Android features
implementation 'org.koin:koin-android:3.2.0'
implementation 'org.koin:koin-androidx-viewmodel:3.2.0'
}

Then, we need to create Koin modules,

import org.koin.dsl.module

val myModule = module {
single { MyRepository() }
factory { MyViewModel(get()) }
// Define other dependencies...
}

single: create an object that persistent with the entire container lifetime. It does not create a new instance with each call.

factory: create a new object each time. Short live. No persistence in the container

In our Application class, we need to initialize Koin by loading the modules,

class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@MyApplication)
modules(myModule)
}
}
}

Using Dependencies in Activity/Fragment,

class MyActivity : AppCompatActivity() {
private val viewModel by viewModel<MyViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use viewModel or other dependencies...
}
}

Now, we can move on to the Hilt,

Hilt that developed by Google and based on Dagger, takes an alternative method. It’s an opinionated DI framework designed specifically for Android and built on top of Dagger, which is known for its robustness and compile-time safety.

Hilt focuses on get advantage from annotations and compile-time checks to ensure correctness and performance. It offers integration with other Jetpack libraries, such as ViewModel and WorkManager, streamlining the process of injecting dependencies into these Android components.

One of Hilt’s major advantages is its extensive support and alignment with the Android development ecosystem. This alignment often makes it the preferred choice for larger projects or those following strict architectural patterns like MVVM or Clean Architecture.

However, Hilt’s learning curve might be steeper due to its ties to Dagger and the specific annotations required. Projects using Hilt might also suffer from increased setup complexity compared to Koin.

Usage of Hilt

Adding Hilt Dependency,

dependencies {
// Other dependencies...
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:$hilt_lifecycle_version"
kapt "androidx.hilt:hilt-compiler:$hilt_lifecycle_version"
}

Enable Hilt in Application,

@HiltAndroidApp
class MyApplication : Application()

Creating Hilt Modules,

@Module
@InstallIn(ApplicationComponent::class)
object MyModule {
@Provides
fun provideMyRepository(): MyRepository {
return MyRepository()
}

@Provides
fun provideMyViewModel(repository: MyRepository): MyViewModel {
return MyViewModel(repository)
}
}

Using dependencies in Activity/Fragment,

@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}

To summarize there are 3 essential differences,

  1. Syntax and Configuration: Koin has more concise and readable syntax focusing on simplicity and ease of use and does not heavily rely on annotations or code generation. However, Hilt uses annotations heavily for dependency injection such as @Inject and @Module.
  2. Learning Curve and Complexity: Koin has Has a gentle learning curve, suitable for developers new to DI and has minimal setup and configuration, reducing complexity. Conversely, Hilt involves more setup and configuration, enforces certain architectural patterns, may have a steeper learning curve due to its close integration with Dagger and specific annotations.
  3. Performance and Optimization: Koin is quick and effective because it doesn’t generate or reflect code, thanks to its lightweight design. Therefore, Koin has a much smaller impact on our built time. However, Hilt needs to use code generation and annotation processing, which could cause build times to increase and the size of the APK to grow. Yet, Koin performs a bit slower at runtime since it resolves dependencies during runtime.

Which one should be preferred?

For smaller projects or flexible solutions, Koin’s simplicity and ease of use might be more useful. Developers may write more modular and maintainable code by utilizing Koin. On the other hand, larger projects or those needing deep integration with Android components could benefit from Hilt’s performance optimizations and alignment with Android architecture components.

References

https://insert-koin.io/docs/reference/koin-core/scopes/#:~:text=By%20default%20in%20Koin%2C%20we,a%20new%20object%20each%20time.

https://treinetic.com/dagger-hilt-koin-and-pure-dependency-injection/#:~:text=Hilt%20takes%20dependency%20injection%20one,injection%20in%20pure%20dependency%20injection.

--

--