Search code examples
androidkotlindependency-injectionkoin

Koin injection from constructor in Kotlin


I can't call inject from constructor for my project via Koin DI.

If I use "... by inject()" for injection the DataRepository class, all works perfectly. But I want to provide inject in a constructor of a class.

I have a crash in the CounterPresenter class in "repo.addPayment(payment)" line. Look down the page.

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964) 
 Caused by: org.koin.error.NoBeanDefFoundException: No compatible definition found. Check your module definition

Here is my structure:

enter image description here

Koin DI Please, how I can change this module for successful working?

val repositoryModule = module {
    single { PrefsManager() }
    single<IRepository> { DataRepository(get() as LocalRepository) }
    single<ILocalRepository> { LocalRepository(get()) }
}

val databaseModule = module {
    single {
        Room.databaseBuilder(androidApplication(), AppDatabase::class.java, Enviroment.DATABASE_NAME).build()
    }
    single { get<AppDatabase>().getCounterDao() }
}

val presentersModule = module {
    factory { CounterPresenter() }
    factory { SplashPresenter() }
}

class DataRepository

class DataRepository(private val localRepository: ILocalRepository) : IRepository {

    init {  Log.d("ROMAN", "init DataRepository") }

    override suspend fun addPayment(payment: Int) {
        localRepository.addPayment(payment)
    }
}

class LocalRepository

class LocalRepository(private val counterDao: CounterDao) : ILocalRepository {

    override suspend fun addPayment(payment: Int) = runBlocking {
        counterDao.insertPayment(Payment(payment))
    }
}

class CounterPresenter

class CounterPresenter : BasePresenter<CounterContract.View>(), CounterContract.Presenter {
    private val repo: DataRepository by inject()


    override fun onViewCreated() {
        super.onViewCreated()
        launchIO { repo.addPayment(payment) }
    }

Solution

  • To inject dependencies to any class, the class must implement KoinComponent interface.(except Activity and Fragments)

    Do this and your code should be working:

    class CounterPresenter : BasePresenter<CounterContract.View>(), CounterContract.Presenter, KoinComponent {
        private val repo: DataRepository by inject()
    
    
        override fun onViewCreated() {
            super.onViewCreated()
            launchIO { repo.addPayment(payment) }
        }
    }