Koin: Can't use injected dependencies

Created on 18 Dec 2017  路  7Comments  路  Source: InsertKoinIO/koin

Hi, i'm new with Koin, and i configured all the stuff but when i tried to use the modules this error came out:

   FATAL EXCEPTION: main
   Process: com.app.careyes, PID: 11583
   java.lang.RuntimeException: java.lang.reflect.InvocationTargetException  
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:448)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
                                                              Caused by: java.lang.reflect.InvocationTargetException
                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)聽
                                                              Caused by: org.koin.error.BeanInstanceCreationException: Can't create bean Bean[name='',class=com.app.careyes.modules.historico.HistoricoPresenter,singleton=true,binds~(com.app.careyes.mvp.contracts.HistoricoContract.Presenter)] due to error : org.koin.error.BeanInstanceCreationException: Can't create bean Bean[name='',class=com.app.careyes.modules.historico.HistoricoInteractor,singleton=true,binds~(com.app.careyes.mvp.contracts.HistoricoContract.Interactor)] due to error : org.koin.error.DependencyResolutionException: Cyclic dependency for class com.app.careyes.mvp.contracts.HistoricoContract$Presenter
                                                                 at org.koin.core.instance.InstanceFactory.createInstance(InstanceFactory.kt:68)
                                                                 at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:32)
                                                                 at org.koin.KoinContext.resolveInstance(KoinContext.kt:58)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment$$special$$inlined$inject$1.invoke(AndroidExt.kt:94)
                                                                 at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment.getPresenter(HistoricoFragment.kt:0)
                                                                 at com.app.careyes.modules.historico.HistoricoFragment$onViewCreated$$inlined$apply$lambda$1.run(HistoricoFragment.kt:51)
                                                                 at android.os.Handler.handleCallback(Handler.java:790)
                                                                 at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                 at android.os.Looper.loop(Looper.java:164)
                                                                 at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                 at java.lang.reflect.Method.invoke(Native Method)聽
                                                                 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)聽
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

And this is my AppModule:

class AppModule : AndroidModule() {
override fun context() = applicationContext {

    context(name = Context.Menu){
        provide { AgendaFragment() }
        provide { MenuFragment() }
        provide { SobreFragment() }
    }

    context(name = Context.Auth) {
        provide { LoginFragment() } bind AuthContract.View::class
        provide { AuthInteractor(get(), get(), get()) } bind AuthContract.Interactor::class
        provide { AuthPresenter(get(), get()) } bind AuthContract.Presenter::class
    }

    context(name = Context.Pacients) {
        provide { PacientsFragment() } bind PacientsContract.View::class
        provide { PacientsPresenter(get(), get()) } bind PacientsContract.Presenter::class
        provide { PacientsInteractor(get(), get(), get()) } bind PacientsContract.Interactor::class
    }

    context(name = Context.Avisos) {
        provide { AvisosFragment() } bind AvisosContract.View::class
        provide { AvisosPresenter(get(), get()) } bind AvisosContract.Presenter::class
        provide { AvisosInteractor(get(), get(), get()) } bind AvisosContract.Interactor::class
    }

    context(name = Context.Historico) {
        provide { HistoricoFragment() } bind HistoricoContract.View::class
        provide { HistoricoPresenter(get(), get()) } bind HistoricoContract.Presenter::class
        provide { HistoricoInteractor(get(), get(), get()) } bind HistoricoContract.Interactor::class
    }

    context(name = Context.Evolucao) {
        provide { EvolucaoFragment() } bind EvolucaoContract.View::class
        provide { EvolucaoInteractor(get(), get(), get()) } bind EvolucaoContract.Interactor::class
        provide { EvolucaoPresenter(get(), get()) } bind EvolucaoContract.Presenter::class
    }

    context(name = Context.NotaEvolucao){
        provide { NotaEvolucaoFragment() } bind NotaEvolucaoContract.View::class
        provide { NotaEvolucaoInteractor(get(),get(),get()) } bind NotaEvolucaoContract.Interactor::class
        provide { NotaEvolucaoPresenter(get(), get()) } bind NotaEvolucaoContract.Presenter::class
    }

    provide { client() }
    provide { sharedPreferences() }
    provide { retrofit(get(), "") }
    provide { careYesApi(get()) }
}

private fun careYesApi(retrofit: Retrofit): CareYesApi {
    return retrofit.create(CareYesApi::class.java)
}

private fun retrofit(okHttpClient: OkHttpClient, base_url: String): Retrofit {
    return Retrofit.Builder()
            .baseUrl(base_url)
            .addConverterFactory(MoshiConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClient)
            .build()
}

private fun client(): OkHttpClient {
    return OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .build()
}

private fun sharedPreferences(): SharedPreferences {
    return androidApplication.getSharedPreferences("User", android.content.Context.MODE_PRIVATE)
}

/**
 * Constantes usadas para definir os escopos das depend锚ncias
 */
object Context {
    val Auth = "Auth"
    val Pacients = "Pacients"
    val Avisos = "Avisos"
    val Historico = "Historico"
    val Evolucao = "Evolucao"
    val Menu = "Menu"
    val NotaEvolucao = "NotaEvolucao"
}
}

what am i missing? Thank you for the attention.

Most helpful comment

Hello,

as I read your stacktrace, there is a cyclic dependency between HistoricoPresenter & HistoricoInteractor. Do those 2 components reference each other in their constructor?

All 7 comments

Hello,

as I read your stacktrace, there is a cyclic dependency between HistoricoPresenter & HistoricoInteractor. Do those 2 components reference each other in their constructor?

Hmm that's right. I'll take a look, i think i can use the interactor without injecting.

As i did here, both classes cannot be instatiate without injecting, because both needs parameters that are not acessible. There's a way to reference each other without this error? Of course, using the MVP with interactor pattern. If not i'll have to move to classic MVP.

Thanks again for the attention.

You can make it in 2 times, and init the injection by one of the two components:

class Presenter(val injector : Injector){
  init{
   injector.presenter = this
  }
}

class Injector(){
  lateinit var presenter : Presenter
}

This way you set injector, in presenter constructor. in MVP, we usually have this kind of 2 times binding because of the MVP contract.

Understood. Last question, what about the the declaration of presenter at AppModule?

actual is this

context(name = Context.Historico) {
        provide { HistoricoFragment() }
        provide { HistoricoPresenter(get(), get()) } bind HistoricoContract.Presenter::class
        provide { HistoricoInteractor(get(), get(), get()) }
    }

Your question is ?

I resolved. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mubarak1361 picture mubarak1361  路  3Comments

leodeleon22 picture leodeleon22  路  4Comments

sankarsana picture sankarsana  路  4Comments

ILAgent picture ILAgent  路  3Comments

AHarazim picture AHarazim  路  3Comments