Inject of bean from a different context
See original GitHub issueDescribe the bug We tried to switch to Koin from Dagger but we run into some strange behavior with the context feature. If we create an object which loads a module inside a class which gets injected we are getting a scope error.
I’ve created a super small project like the following:
The MainActivity starting Koin and injecting an class Sdk
class MainActivity : AppCompatActivity() {
val sdk: Sdk by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startKoin(listOf(AppModule().module))
sdk.toString()
}
}
The AppModule only has one bean for the Sdk
class AppModule {
val module = applicationContext {
bean { Sdk() }
}
}
The Sdk class itself contains a Backend object (no injection, only the object)
class Sdk {
val backend: Backend = Backend()
init {
backend.toString()
}
}
The Backend-class itself is a KoinComponent loading a BackendModule and injecting a class called Bar. Consider this a library with its oun context.
class Backend : KoinComponent {
val bar: Bar by inject()
init {
loadKoinModules(listOf(BackendModule().module))
bar.toString()
}
}
BackendModule includes a bean inside a context with name “backend”
class BackendModule {
val module = applicationContext {
context("backend") {
bean { Bar() }
}
}
}
The line in the Sdk class where the Backend gets created is crashing with the following stacktrace:
06-22 12:09:13.092 30620-30620/com.example.mirko.testcontextrelease W/System.err: org.koin.error.ContextVisibilityException: Can't resolve 'com.example.mirko.testcontextrelease.Bar' for definition Bean[class=com.example.mirko.testcontextrelease.Sdk].
Class 'com.example.mirko.testcontextrelease.Bar' is not visible from context scope Scope[ROOT]
at org.koin.KoinContext.getVisibleBeanDefinition(KoinContext.kt:111)
at org.koin.KoinContext.resolveInstance(KoinContext.kt:77)
at com.example.mirko.testcontextrelease.Backend$$special$$inlined$inject$1.invoke(KoinComponent.kt:114)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at com.example.mirko.testcontextrelease.Backend.getBar(Unknown Source:7)
at com.example.mirko.testcontextrelease.Backend.<init>(Backend.kt:14)
at com.example.mirko.testcontextrelease.Sdk.<init>(Sdk.kt:4)
at com.example.mirko.testcontextrelease.AppModule$module$1$1.invoke(AppModule.kt:8)
at com.example.mirko.testcontextrelease.AppModule$module$1$1.invoke(AppModule.kt:5)
06-22 12:09:13.093 30620-30620/com.example.mirko.testcontextrelease W/System.err: at org.koin.core.instance.InstanceFactory.createInstance(InstanceFactory.kt:58)
at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:26)
at org.koin.KoinContext$resolveInstance$$inlined$synchronized$lambda$1.invoke(KoinContext.kt:85)
at org.koin.KoinContext$resolveInstance$$inlined$synchronized$lambda$1.invoke(KoinContext.kt:23)
at org.koin.ResolutionStack.resolve(ResolutionStack.kt:23)
at org.koin.KoinContext.resolveInstance(KoinContext.kt:80)
at com.example.mirko.testcontextrelease.MainActivity$$special$$inlined$inject$1.invoke(AndroidExt.kt:179)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at com.example.mirko.testcontextrelease.MainActivity.getSdk(Unknown Source:7)
06-22 12:09:13.094 30620-30620/com.example.mirko.testcontextrelease W/System.err: at com.example.mirko.testcontextrelease.MainActivity.onCreate(MainActivity.kt:19)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
06-22 12:09:13.095 30620-30620/com.example.mirko.testcontextrelease W/System.err: 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)
06-22 12:09:13.096 30620-30620/com.example.mirko.testcontextrelease D/AndroidRuntime: Shutting down VM
06-22 12:09:13.098 30620-30620/com.example.mirko.testcontextrelease E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mirko.testcontextrelease, PID: 30620
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mirko.testcontextrelease/com.example.mirko.testcontextrelease.MainActivity}: org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=com.example.mirko.testcontextrelease.Sdk] due to error :
org.koin.error.ContextVisibilityException: Can't resolve 'com.example.mirko.testcontextrelease.Bar' for definition Bean[class=com.example.mirko.testcontextrelease.Sdk].
Class 'com.example.mirko.testcontextrelease.Bar' is not visible from context scope Scope[ROOT]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
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)
Caused by: org.koin.error.BeanInstanceCreationException: Can't create bean Bean[class=com.example.mirko.testcontextrelease.Sdk] due to error :
org.koin.error.ContextVisibilityException: **Can't resolve 'com.example.mirko.testcontextrelease.Bar' for definition Bean[class=com.example.mirko.testcontextrelease.Sdk].
Class 'com.example.mirko.testcontextrelease.Bar' is not visible from context scope Scope[ROOT]**
at org.koin.core.instance.InstanceFactory.createInstance(InstanceFactory.kt:63)
at org.koin.core.instance.InstanceFactory.retrieveInstance(InstanceFactory.kt:26)
at org.koin.KoinContext$resolveInstance$$inlined$synchronized$lambda$1.invoke(KoinContext.kt:85)
at org.koin.KoinContext$resolveInstance$$inlined$synchronized$lambda$1.invoke(KoinContext.kt:23)
at org.koin.ResolutionStack.resolve(ResolutionStack.kt:23)
at org.koin.KoinContext.resolveInstance(KoinContext.kt:80)
at com.example.mirko.testcontextrelease.MainActivity$$special$$inlined$inject$1.invoke(AndroidExt.kt:179)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:131)
at com.example.mirko.testcontextrelease.MainActivity.getSdk(Unknown Source:7)
at com.example.mirko.testcontextrelease.MainActivity.onCreate(MainActivity.kt:19)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
... 9 more
It can not resolve Bar in Backend of scope ROOT - but this seems to be wrong.
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (4 by maintainers)
Things should be clearer in
1.0.0
. Wait the next weeks for new documentation 👍Maybe i can help you: You have two modules: AppModule and BackendModule
The Sdk class is provided in the AppModule with root context. The Backend class which you want to inject in the Sdk class needs a Bar class which is provided in the BackendModule in another context “backend”.
So the usage of context is the following:
root: knows only classes/interfaces/… from the root context backend: knows classes from the root context AND the backend context
So your problem is that the Sdk class from the root context needs injects a Backend class which needs a class (Bar) from the backend context. And this is not visible in the root context. See the error message: