What is DI (dependency injection)?
Dependency Injection is a design pattern used to implement inverse of control, meaning the flow of an application is inverted. We can create the dependent object outside of the class and provide those object to class from different ways. DI can help with, moving the creation and binding of the dependent objects outside of the class that depends on them.
There are main 4 roles in DI
If you want to use this technique, you need classes that fulfil four basic roles. These are:
- The service you want to use.
- The client uses the service.
- An interface that’s used by the client and implemented by the service.
- The injector which makes a service instance and injects it into the client.
I hope you have understood DI and a little bit about koin.
How Koin Works
The koin works on simple DSL model. Here we have to create module first. In this module all the dependent objects are there, then we have to load one or more modules in koin. Then, we are ready to use this object. Generally we are loading module in to koin in application class by calling startKoin method,then we can inject the object wherever we want,this how the Koin works.
Koin Vs Dagger
Koin | Dagger |
---|---|
Easy to learn and maintain | Hard to understand and maintain |
Purely written in Kotlin | Written in JAVA |
Works on DSL module | Uses annotation processing |
Getting runtime Errors | Showing Errors at compile time |
Developed by Frech developer | Supported by Google |
Having a library for ViewModel integration | Does not have any special thing to interact with ViewModel |
Having a dedicated log on every object creation | Does not have any kind of logging feature |
Generate less number of line of code | Generates more number of line of code then Koin |
Setting up Koin
- Gradle Setup
repositories { jcenter() }dependencies { implementation 'org.koin:koin-android:2.0.1' }
- Setup for MVVM extension
repositories { jcenter() } dependencies { // ViewModel for Android implementation 'org.koin:koin-android-viewmodel:2.0.1' // or ViewModel for AndroidX implementation 'org.koin:koin-androidx-viewmodel:2.0.1' }
Yeee! we have successfully completed the setup
Why to Use Koin?
The very simple answer, to this question, other options are very hard to understand like dagger 2 and having bolipater code, and options like toothpick and many more cannot able to integrate, with ViewModel, Scope Model, Ktor, where as Koin can easily integratable. Koin have it own separate testing module that helps to performing testing.koin uses its own DSL, rather than annotations, Koin DSL Composed of this five things.
- Application context
- Bean
- Factory
- Bind
- Get
Example
Simple example
- We have to create module of dependency that we need to inject
val myModule = module { single{ BusinessService()} } //class object which is going to injected class BusinessService() { init { Log.d("BusinessService", "Created") } var data = "hello" }
- Now we have successfully created a module now we need to pass it to koin for loading it.
class KoinDemo : Application() { override fun onCreate() { super.onCreate() startKoin { androidContext(this@KoinDemo) modules(myModule) //modules(mySecoundModule) } } }
- Here we are ready to Inject.
val businessService: BusinessService by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) businessService.data }
All done successfully, this quite simple, isn’t it?
MVVM example
ViewModel Support
Simple integration is just the tip of the iceberg. There are a lot of features that Koin provides. Most importantly, it supports architecture component’s ViewModel. This feature binds Koin more strongly with the android community, no?
Let’s dive into an example to see its usefulness.
- Creating ViewModel Class
class MainActivityVM(var view: MainActivityView) : ViewModel() { var userName = ObservableField<String>() var password = ObservableField<String>() fun onSubmitClick() { if (userName.get().equals("yudiz") && password.get().equals("yudiz123")) { view.showToast("welcome") } else { view.showToast("incorrect data") } } }
- Creating koin module
val mvvmModuleDI = module { viewModel { (view: MainActivityView) -> MainActivityVM(view) } }
- Adding module to Koin
startKoin { // Android context androidContext(this@KoinDemo) modules(mvvmModuleDI) }
- Injecting viewModel to Activity
class MvvmWithKoin : AppCompatActivity(), MainActivityView { override fun showToast(msg: String) { Toast.makeText(this, msg, Toast.LENGTH_LONG).show() } //injecting viewModel val viewModel: MainActivityVM by viewModel { parametersOf(this) } lateinit var binding: ActivityMvvmWithKoinBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_mvvm_with_koin) binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvm_with_koin) binding.viewModelKoin = viewModel } }
Conclusion
Koin is as fast as dagger yet is easy to learn, it does not have any boilerplate code and it is a very powerful framework for Kotlin developers to use as dependency injection. So what are you waiting for, just implement it and enjoy