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