6

I am using Koin di library in my project. Version of lib is 1.0.0-RC-1.

My module:

val appModule = module {
    scope("UserScope") { UserToaster(androidContext()) as Toaster }
    scope("AnonScope") { AnonToaster(androidContext()) as Toaster }
}

I started koin in my Application class and created scope:

override fun onCreate() {
    super.onCreate()

    startKoin(this, listOf(appModule))
    getKoin().getOrCreateScope("AnonScope")
}

And next I tried to inject implementation of Toaster from current scope to variable in Activity. Here the code:

private val toaster: Toaster by inject(scope = "AnonScope")

After this I got an error:

Caused by: org.koin.error.DependencyResolutionException: Multiple definitions found for type 'interface com.example.nkirilov.playground.Toaster (Kotlin reflection is not available)' - Koin can't choose between :
    Scope [name='UserScope',class='com.example.nkirilov.playground.Toaster']
    Scope [name='AnonScope',class='com.example.nkirilov.playground.Toaster']
    Check your modules definition, use inner modules visibility or definition names.

I do not understand why this does not work (If use single with different names - it will work). Is that koin bug? How to avoid this error?

KolinLoures
  • 130
  • 2
  • 10

2 Answers2

2

I implemented it like this

Module:

val navigationModule = module {
    scope(DI.APP_SCOPE) { ClassA().create }
    scope(DI.APP_SCOPE) { get(scopeId = DI.APP_SCOPE).classB }
    scope(DI.APP_SCOPE) { get(scopeId = DI.APP_SCOPE).classC }
}

val authModule = module {
    scope(DI.AUTH_SCOPE) { ClassA.create(ChildClassB(get(scopeId = DI.APP_SCOPE))) }
    scope(DI.AUTH_SCOPE) { get(scopeId = DI.AUTH_SCOPE).classB }
    scope(DI.AUTH_SCOPE) { get(scopeId = DI.AUTH_SCOPE).classC }
}

Main Activity:

private val classC: ClassC by inject(scope = getKoin().getOrCreateScope(APP_SCOPE))

AuthActivity:

private val classC: ClassC by inject(scope = getKoin().getOrCreateScope(DI.AUTH_SCOPE))
Vitali
  • 694
  • 5
  • 12
0

your definitions have the same name in Koin. Current version (~1.0.*) avoid you to specify which scope to use, by automating resolving a type and it's session id.

Can you avoid describe your definitions with same type, like:

val appModule = module {
    scope("UserScope") { UserToaster(androidContext()) }
    scope("AnonScope") { AnonToaster(androidContext()) }
}

Else we would need a feature to specify which scope to use when resolving a type. You would resolve it with:

val userScope = getScope("UserScope")
get<Toaster>(scope = userScope)
  • It did not work for me. I created a sample project on Github, if you will be free, check it, please. [Here link:] (https://github.com/KolinLoures/TestScopeKoin). TIA – KolinLoures Sep 09 '18 at 17:46
  • 1
    let me check that – Arnaud Giuliani Sep 10 '18 at 07:59
  • edited my comment. Can you use directly your types for now? – Arnaud Giuliani Sep 10 '18 at 13:40
  • Unfortunately, i can't. In my work project, I need to set implementation in according what scope had created. May be, Is there another approach to realize this idea? – KolinLoures Sep 10 '18 at 15:39
  • May be use this: getKoin().get( clazz = Toaster::class, filter = { a: BeanDefinition<*> -> a.attributes["scope"] == currentScope.id } ) – KolinLoures Sep 12 '18 at 12:39
  • 2
    a bit hard to find it like that, but the main thing is that visibility is not restraint against with the scope. You can raise an issue on github. – Arnaud Giuliani Sep 12 '18 at 14:44
  • @ArnaudGiuliani Could you please check [this question](https://stackoverflow.com/q/73235897/813951)? We need an authoritative reference. – Mister Smith Aug 17 '22 at 12:15
  • This is a bit outdated, this question address Koin 1.x. In Koin 3.x, you can retrieve a scope with koin.getScope( /* scopeId */ ) On the Scope object, you can resolve your dependency with get() or inject(). Check the online documentation: https://insert-koin.io/docs/reference/koin-core/scopes#scope-id--scope-name – Arnaud Giuliani Aug 22 '22 at 14:53