What is Koin?
Koin is a pragmatic lightweight dependency injection framework for Kotlin developers.
-> Source: https://github.com/InsertKoinIO/koin
-> Official: https://insert-koin.io/
How to Setup?
See -> Setup
.. also -> koin-android
Ready MVP Android Code Before apply DI
Code over view before applying koin.
It's popular mvp.
View -> Presenter -> UseCase -> Repositry
// add a class inherited Application for setup koin
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
}
}
// presentation layer
object GreetContract {
interface View {
fun showGreet(greet: Greet): Unit
}
interface Presenter {
fun loadGreet()
}
}
class MainActivity
: AppCompatActivity(), GreetContract.View {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
// loadGreet
}
}
override fun showGreet(greet: Greet) {
textView.text = greet.helloWords
}
}
class GreetPresenter(
private val view: GreetContract.View,
private val countryProvider: () -> Country, // add lambda
private val getGreetUseCase: GetGreetUseCase
) : GreetContract.Presenter {
override fun loadGreet() {
val greet = getGreetUseCase.execute(countryProvider())
view.showGreet(greet)
}
}
// model layer
sealed class Greet(val helloWords: String){
object JpKonichiha: Greet("こんにちは!")
object USHello: Greet("Hello!")
object Emoji: Greet("\uD83D\uDC4B")
}
enum class Country {
JP, US, OTHER;
companion object {
fun countryProvider(): () -> Country {
var count = 0
return {
when(count++%3) { // it's not a implementation for thread safe.
0 -> Country.JP
1 -> Country.US
else -> Country.OTHER
}
}
}
}
}
class GetGreetUseCase(
private val greetRepository: GreetRepository
) {
fun execute(country: Country): Greet = greetRepository.get(country)
}
// data layer
interface GreetRepository {
fun get(country: Country): Greet
}
class GreetRepositoryImpl: GreetRepository {
override fun get(country: Country): Greet {
return when(country) {
Country.JP -> Greet.JpKonichiha
Country.US -> Greet.USHello
Country.OTHER -> Greet.Emoji
}
}
}
Apply Koin
diff
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
+ startKoin(this, listOf(appModules))
}
+ private val appModules = module {
+ single<GreetRepository> { GreetRepositoryImpl() } // single intance
+ factory { GetGreetUseCase(get()) }
+ factory { Country.countryProvider() }
+ factory<GreetContract.Presenter> { (cv: GreetContract.View) ->
+ GreetPresenter(cv, get(), get())
+ } // add lambda argument to get `cv` in inject timing.
+ }
}
// presentation layer
class MainActivity
: AppCompatActivity(), GreetContract.View {
+ val presenter: GreetContract.Presenter by inject { parametersOf(this) } // set for cv
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
- // loadGreet
+ presenter.loadGreet()
}
}
override fun showGreet(greet: Greet) {
textView.text = greet.helloWords
}
}
build app ...
(i made gif at https://ezgif.com/video-to-gif)
Other
-
single<Foo>/factory<Foo>
oras Foo
orbind Foo:class
?-
bind
is for a multiple type definition likeRepository
andRepositoryImpl
-
<Foo>
andas Foo
is same definition.
-
-
How to apply in MVVM(Android Architecture ViewModel)
- use
viewModel
injection utils. -> koin:Android Architecture ViewModel
- use
How is it ?
I feel very easy to use Koin to Android layerd architecture for testable. It's a so Simple .
Comparation with Dagger
I haven't used dagger/dagger2 in Production I joined.