Skip to content

Instantly share code, notes, and snippets.

@Nek-12
Last active March 29, 2024 14:45
Show Gist options
  • Save Nek-12/daadb9c17ee0aa8682c50626811882b0 to your computer and use it in GitHub Desktop.
Save Nek-12/daadb9c17ee0aa8682c50626811882b0 to your computer and use it in GitHub Desktop.
Koin <> Decompose Generic Component with injection
// warning - the descendants must be retained across config changes
@Stable
interface DestinationScope : KoinScopeComponent {
val coroutineScope: CoroutineScope
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
}
val LocalDestinationScope = staticCompositionLocalOf<DestinationScope> {
error("Provide a destination scope")
}
@FlowMVIDSL
inline fun <reified T : Container<*, *, *>> Module.container(noinline definition: Definition<T>) {
scope<DestinationScope> {
scoped<T> { params ->
definition(this, params).apply {
store.start(get<CoroutineScope>())
}
}
}
}
@FlowMVIDSL
@Composable
inline fun <reified T : Container<S, I, A>, S : MVIState, I : MVIIntent, A : MVIAction> container(
noinline params: ParametersDefinition? = null,
) = koinInject<T>(scope = LocalDestinationScope.current.scope, parameters = params).store
// navigation module ->
@Stable
internal interface DestinationComponent : ComponentContext, DestinationScope
internal fun destinationComponent(
destination: Destination?, // ~ Configuration
context: ComponentContext
): DestinationComponent = object : ComponentContext by context, DestinationComponent {
override val scope = getKoin().getOrCreateScope(
scopeId = destination?.getScopeId() ?: "RootComponent",
qualifier = qualifier<DestinationScope>(),
source = context as? DestinationScope
)
override val coroutineScope = coroutineScope()
init {
scope.declare(instance = coroutineScope, allowOverride = false)
context.typed<DestinationScope>()?.let { scope.linkTo(it.scope) }
doOnDestroy { scope.close() }
}
override fun equals(other: Any?): Boolean {
if (other !is DestinationComponent) return false
return scope.id == other.scope.id
}
override fun hashCode(): Int = scope.hashCode()
}
@Composable
internal fun ProvideDestinationLocals(
component: DestinationComponent,
content: @Composable () -> Unit
) = CompositionLocalProvider(
LocalSubscriberLifecycle provides rememberSubscriberLifecycle(component.lifecycle) { asSubscriberLifecycle },
LocalDestinationScope provides component,
LocalKoinScope provides component.scope,
content = content,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment