Skip to content

Commit

Permalink
Optimize scope allocation in Compose
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaudgiuliani committed Nov 6, 2024
1 parent a2df2bc commit cd36752
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ import org.koin.viewmodel.resolveViewModel
@Composable
inline fun <reified T : ViewModel> koinViewModel(
qualifier: Qualifier? = null,
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
viewModelStoreOwner: ViewModelStoreOwner = LocalViewModelStoreOwner.current ?: error("No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"),
key: String? = null,
extras: CreationExtras = defaultExtras(viewModelStoreOwner),
scope: Scope = currentKoinScope(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ import org.koin.viewmodel.resolveViewModel
@Composable
inline fun <reified T : ViewModel> koinViewModel(
qualifier: Qualifier? = null,
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
viewModelStoreOwner: ViewModelStoreOwner = LocalViewModelStoreOwner.current ?: error("No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"),
key: String? = null,
extras: CreationExtras = defaultExtras(viewModelStoreOwner),
scope: Scope = currentKoinScope(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.InternalComposeApi
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.RememberObserver
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.currentComposer
import androidx.compose.runtime.remember
import org.koin.compose.application.rememberKoinApplication
import org.koin.compose.error.UnknownKoinContext
import org.koin.compose.scope.rememberKoinScope
import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.annotation.KoinInternalApi
import org.koin.core.error.ClosedScopeException
import org.koin.core.scope.Scope
import org.koin.dsl.KoinAppDeclaration
import org.koin.dsl.koinApplication
Expand Down Expand Up @@ -77,18 +81,25 @@ fun getKoin(): Koin = currentComposer.run {
*/
@OptIn(InternalComposeApi::class, KoinInternalApi::class)
@Composable
@ReadOnlyComposable
//fun currentKoinScope(): Scope = LocalKoinScope.current
fun currentKoinScope(): Scope = currentComposer.run {
remember {
try {
consume(LocalKoinScope)
} catch (_: UnknownKoinContext) {
val ctx = getDefaultKoinContext()
warningNoContext(ctx)
getDefaultKoinContext().scopeRegistry.rootScope
try {
consume(LocalKoinScope)
} catch (_: UnknownKoinContext) {
getDefaultKoinContext().let {
warningNoContext(it)
it.scopeRegistry.rootScope
}
} catch (e: ClosedScopeException) {
getDefaultKoinContext().let {
it.logger.warn("Try to refresh scope - fallback on default context from - $e")
it.scopeRegistry.rootScope
}
}
}


@OptIn(KoinInternalApi::class)
private fun warningNoContext(ctx: Koin) {
ctx.logger.error("[Warning] - No Compose Koin context setup, taking default. Use KoinContext(), KoinAndroidContext() or KoinApplication() function to setup or create Koin context and avoid such message.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@
package org.koin.compose.scope

import androidx.compose.runtime.RememberObserver
import org.koin.core.Koin
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.core.annotation.KoinInternalApi
import org.koin.core.scope.Scope

@KoinExperimentalAPI
@KoinInternalApi
class CompositionKoinScopeLoader(
val scope: Scope,
val koin : Koin
val scope: Scope
) : RememberObserver {

override fun onRemembered() {
Expand All @@ -41,7 +39,9 @@ class CompositionKoinScopeLoader(
}

private fun close() {
koin.logger.debug("$this -> close scope id: '${scope.id}'")
scope.close()
if (!scope.isRoot && !(scope.closed)){
scope.logger.debug("CompositionKoinScopeLoader close scope: '${scope.id}'")
scope.close()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ import org.koin.core.scope.ScopeID
*/
@KoinExperimentalAPI
@Composable
inline fun rememberKoinScope(scope: Scope): Scope {
val koin = getKoin()
fun rememberKoinScope(scope: Scope): Scope {
val wrapper = remember(scope) {
CompositionKoinScopeLoader(scope, koin)
CompositionKoinScopeLoader(scope)
}
return wrapper.scope
}

0 comments on commit cd36752

Please sign in to comment.