What is KOIN?
A pragmatic lightweight dependency injection framework for Kotlin developers.
Written in pure Kotlin, using functional resolution only: no proxy, no code generation, no reflection.
Koin is a DSL, a light container and a pragmatic API
https://insert-koin.io
Official Documentation now onAll documentation, sample and references has been move to our website. Check the official website to get started: insert-koin.io. Koin samples project are located here: koin-samples
You can check the getting started section from our website, to discover Koin with the favorite platform. Or follow the snippets below.
Contact & Support
Follow us on Twitter for latest news: @insertkoin_io
Need help? Come on slack Koin channel from Kotlin slack. Or just open an issue on Github issues to share your problem.
Setup
Actual Version
koin_version = '0.9.3'
Gradle
Check that you have the jcenter
repository.
// Add Jcenter to your repositories if needed
repositories {
jcenter()
}
Choose your the Koin module:
// Koin for Kotlin
compile "org.koin:koin-core:$koin_version"
// Koin for Android
compile "org.koin:koin-android:$koin_version"
// Koin for Android Architecture Components
compile "org.koin:koin-android-architecture:$koin_version"
// Koin for Spark Kotlin
compile "org.koin:koin-spark:$koin_version"
// Koin for Ktor Kotlin
compile "org.koin:koin-ktor:$koin_version"
// Koin for JUnit tests
testCompile "org.koin:koin-test:$koin_version"
Quickstart
- Your first dependency with Android
- Your first dependency with Android and ViewModel
- Unit Testing with Koin
- The Koin DSL in 5 minutes
Getting Started
Your first dependency with Android
Gradle
compile "org.koin:koin-android:$koin_version"
Declaring our first dependencies
Let's create a Repository to provide some data (giveHello()
):
interface Repository {
fun giveHello(): String
}
class MyRepository() : Repository {
override fun giveHello() = "Hello Koin"
}
A Presenter class, for consuming this data:
// Use Repository - injected by constructor by Koin
class MyPresenter(val repository : Repository){
fun sayHello() = repository.giveHello()
}
Use the applicationContext
function to declare a module. Let's write our dependencies via constructor injection:
// Koin module
val myModule : Module = applicationContext {
factory { MyPresenter(get()) } // get() will resolve Repository instance
bean { MyRepository() as Repository }
}
By using the factory definition for our presenter, we will obtain a new instance each time we ask about the MyPresenter
class.
Start Koin
Now that we have a module, let's start it with Koin. Open your application class, or make one (don't forget to declare it in your manifest.xml). Just call the startKoin()
function:
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
// Start Koin
startKoin(this, listOf(myModule))
}
}
Injecting dependencies
The MyPresenter
component will be created with Repository
instance. To get it from our Activity, let's inject it with the by inject()
delegate injector (we can't directly create Activitiy instances from Koin):
class MyActivity : AppCompatActivity(){
// Inject MyPresenter
val presenter : MyPresenter by inject()
override fun onCreate() {
super.onCreate()
// Let's use our presenter
Log.i("MyActivity","presenter : ${presenter.sayHello()}")
}
}
Your first dependency with Android ViewModel
Gradle
compile "org.koin:koin-android-architecture:$koin_version"
Declaring our first dependencies
Let's create a Repository to provide some data (giveHello()
):
interface Repository {
fun giveHello(): String
}
class MyRepository() : Repository {
override fun giveHello() = "Hello Koin"
}
A ViewModel class, for consuming this data:
// Use Repository - injected by constructor by Koin
class MyViewModel(val repository : Repository) : ViewModel(){
fun sayHello() = repository.giveHello()
}
Use the applicationContext
function to declare a module. Let's write our dependencies via constructor injection:
// Koin module
val myModule : Module = applicationContext {
viewModel { MyViewModel(get()) } // get() will resolve Repository instance
bean { MyRepository() as Repository }
}
We are also using the viewModel
keyword to declare an Android ViewModel component.
Start Koin
Now that we have a module, let's start it with Koin. Open your application class, or make one (don't forget to declare it in your manifest.xml). Just call the startKoin()
function:
class MyApplication : Application(){
override fun onCreate() {
super.onCreate()
// Start Koin
startKoin(this, listOf(myModule))
}
}
Injecting dependencies
The MyViewModel
component will be created with Repository
instance. To get it from our Activity, let's inject it with the by viewModel()
delegate injector (we can't directly create Activitiy instances from Koin):
class MyActivity : AppCompatActivity(){
// Inject MyViewModel
val myViewModel : MyViewModel by viewModel()
override fun onCreate() {
super.onCreate()
// Let's use our ViewModel
Log.i("MyActivity","ViewModel : ${myViewModel.sayHello()}")
}
}
Or if you want to eagerly create your ViewModel in a function, just use the getViewModel()
:
class MyActivity : AppCompatActivity(){
override fun onCreate() {
super.onCreate()
val myViewModel : MyViewModel = getViewModel()
// Let's use our ViewModel
Log.i("MyActivity","ViewModel : ${myViewModel.sayHello()}")
}
}
Unit Testing with Koin
Gradle Setup
First, add the Koin dependency like below:
// Add Jcenter to your repositories if needed
repositories {
jcenter()
}
dependencies {
// Koin testing tools
testcompile 'org.koin:koin-test:{{ site.current_version }}'
}
Declared dependencies
Let's create a Repository to provide some data (giveHello()
):
interface Repository {
fun giveHello(): String
}
class MyRepository() : Repository {
override fun giveHello() = "Hello Koin"
}
A Presenter class, for consuming this data:
// Use Repository - injected by constructor by Koin
class MyPresenter(val repository : Repository){
fun sayHello() = repository.giveHello()
}
Use the applicationContext
function to declare a module. Let's declare our first component:
// Koin module
val myModule : Module = applicationContext {
bean { MyPresenter(get()) } // get() will resolve Repository instance
bean { MyRepository() as Repository }
}
Writing our first Test
To make our first test, let's write a simple Junit test file and extend it with KoinTest
. We will be able then, to use by inject()
operators.
class FirstTest : KoinTest {
val presenter : MyPresenter by inject()
val repository : Repository by inject()
@Before
fun before(){
startKoin(listOf(myModule))
}
@After
fun after(){
closeKoin()
}
@Test
fun testSayHello() {
assertEquals(repository.giveHello(), presenter.sayHello())
}
}
The KOIN DSL in 5 minutes
Keywords
A quick recap of the Koin DSL keywords:
applicationContext
- create a Koin Modulefactory
- provide a factory bean definitionbean
- provide a bean definitionbind
- additional Kotlin type binding for given bean definitionget
- resolve a component dependencygetProperty
- resolve a propertycontext
- declare a logical context
Special keywords:
viewModel
- declare an Android ViewModel (koin-android-architecture only)controller
- declare a SparkJava controller (koin-spark only)
Deprecated: provide
has been deprecated in favor to aliases. bean ~ provide
and factory ~ provide(isSingleton=false)
Writing a module
Here below the Koin DSL keywords you need to know, to write your module. To declare a module, use the applicationContext
function:
val myModule = applicationContext {
// your dependencies here
}
The applicationContext
lambda function is where you will write your definitions. myModule
is the Koin module
To define your components, use the following keywords:
bean
- define a singleton (create only one instance)factory
- define a factory (create a new instance each time)
Deprecated: provide
keyword is now deprecated. Please use bean
or factory
Below a simple definition of a MyRepository
singleton:
class MyRepository()
val myModule = applicationContext {
bean { MyRepository() }
}
Binding interfaces or several types
To bind a component with its interface, we have 2 solutions. Given an interface and its implmentation:
class MyRepositoryImpl()
interface MyRepository
We can write it:
bean { MyRepositoryImpl() as MyRepository }
- will create an instance of typeMyRepository
bean { MyRepositoryImpl() } bind MyRepository::class
- will create an instance of typeMyRepositoryImpl
and will accept to bind on typeMyRepository
*You can use the bind
keyword with a class several times: bind Class1::class bind Class2::class
Multiple definitions of the same type
If you have mulitple definitions of the same type, Koin can't guess which instance to use. Then, you have to name each instance to clearly specify which instance to use. bean
and factory
have the name
parameter (default parameter).
class MyLocalRepositoryImpl()
class MyRemoteRepositoryImpl()
interface MyRepository
we will write our module like:
val myModule = applicationContext {
bean("local") { MyLocalRepositoryImpl() as MyRepository }
bean("remote") { MyRemoteRepositoryImpl() as MyRepository }
}
Resolving a dependency
Koin push you to use constructor injection to bind your component. Given classes:
class ComponentA()
class ComponentB(val componentA : ComponentA)
We wil use the get()
function to resolve a dependency:
val myModule = applicationContext {
bean { ComponentA() }
bean { ComponentB(get()) }
}
Using multiple modules / Module import
Every definition and module is lazy be default in Koin. This means that you can assemble several modules, by using the list of desired modules. Given some classes:
class ComponentA()
class ComponentB(val componentA : ComponentA)
And the two modules to declare it:
val myModule1 = applicationContext {
bean { ComponentA() }
}
val myModule2 = applicationContext {
bean { ComponentB(get()) }
}
Just start the module list together:
// Android Start
startKoin(this,listOf(module1,module2))
// Kotlin/Spark Start
startKoin(listOf(module1,module2))
Articles
Koin Developers Hub
Koin on Medium:Last articles
- Koin 0.9.2 — Maintenance fixes, new branding, roadmap for 1.0.0 & some other nice announces
- Koin 0.9.1 - Bug fixes & Improvments
- Koin 0.9.0 - Getting close to stable
- Unlock your Android ViewModel power with Koin
- Koin + Spark = ❤️
- koin 0.8.2 Improvements bugfixes and crash fix
- Koin release 0.8.0
- Push SparkJava to the next level (Kotlin Weekly issue 73, DZone.com )
- When Koin met Ktor ... (Kotlin Weekly issue 72)
- Moving from Dagger to Koin - Simplify your Android development - (Kotlin Weekly issue 66 & Android Weekly issue 282)
- Kotlin Weekly #64
- Insert Koin for dependency injection
- Better dependency injection for Android