[Android] Using Koin 1.x in MVP-Repository Pattern for DI

### 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](https://github.com/InsertKoinIO/koin#setup)
 .. also -> [koin-android](https://start.insert-koin.io/#/getting-started/koin-for-android)

### Ready MVP Android Code Before apply DI

Code over view before applying koin.
It's popular mvp.
`View -> Presenter -> UseCase -> Repositry`

```Kotlin
// 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

```kotlin
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 ...
![koinSample.gif](https://qiita-image-store.s3.amazonaws.com/0/307296/e8206248-05b7-3eae-2fd2-cdc47bc7827c.gif)
(i made gif at https://ezgif.com/video-to-gif)

### Other
- `single<Foo>/factory<Foo>` or `as Foo` or `bind Foo:class`?
    - `bind` is for a multiple type definition like `Repository` and `RepositoryImpl`
    - `<Foo>` and `as Foo` is same definition.

- How to apply in MVVM(Android Architecture ViewModel)
    - use `viewModel` injection utils. -> [koin:Android Architecture ViewModel](https://start.insert-koin.io/#/getting-started/koin-for-android?id=android-viewmodel)


### 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.