LoginSignup
5
5

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-10-27

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 ...
koinSample.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)

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.

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5