InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
8.77k stars 695 forks source link

LocalKoinScope stuck with a closed scope #1900

Open tlevavasseur-decathlon opened 5 days ago

tlevavasseur-decathlon commented 5 days ago

Describe the bug The issue was present in 3.4.X :

@Composable
inline fun <reified T> koinInject(
    qualifier: Qualifier? = null,
    scope: Scope = LocalKoinScope.current,
    noinline parameters: ParametersDefinition? = null,
): T = rememberKoinInject(qualifier, scope, parameters)

@OptIn(KoinInternalApi::class)
val LocalKoinScope = compositionLocalOf { getKoinContext().scopeRegistry.rootScope }

fixed in 3.5.0 :

@Composable
inline fun <reified T> koinInject(
    qualifier: Qualifier? = null,
    scope: Scope = getKoinScope(),
    noinline parameters: ParametersDefinition? = null,
): T = rememberKoinInject(qualifier, scope, parameters)

@OptIn(InternalComposeApi::class)
@Composable
fun getKoinScope(): Scope = currentComposer.run {
    remember {
        try {
            consume(LocalKoinScope)
        } catch (_: UnknownKoinContext) {
            val ctx = getKoinContext()
            warningNoContext(ctx)
            getKoinContext().scopeRegistry.rootScope
        }
    }
}

val LocalKoinScope: ProvidableCompositionLocal<Scope> = 
    compositionLocalOf { throw UnknownKoinContext() }

but reintroduced in 3.5.3 :

val LocalKoinScope: ProvidableCompositionLocal<Scope> = compositionLocalOf {
    getDefaultKoinContext().apply {
        warnNoContext()
    }.scopeRegistry.rootScope
}

private fun getDefaultKoinContext() = KoinPlatformTools.defaultContext().get()

We get stuck with a closed scope, the one active on initialization of LocalKoinScope.

To Reproduce a simple way to test it is to restart koin and the activity :

MainActivity : 

        Button(onClick = {
            restartKoin()
            context.startActivity(Intent(context, MainActivity::class.java))
        })

fun restartKoin() {
    stopKoin()
    koin = startKoin {  ... }
}

Expected behavior Like with 3.5.0 : when a new activity wants the LocalKoinScope (with koinInject()) get the currently available Koin instance.