Skip to main content
Version: 4.2

Dynamic Modules

This page covers rememberKoinModules, which loads Koin modules when a Composable enters the composition and can unload them when it leaves. Use it to load the definitions of a feature only when its screen is shown. You should know how to declare modules.

rememberKoinModules is in io.insert-koin:koin-compose and is marked @KoinExperimentalAPI.

rememberKoinModules​

import org.koin.compose.module.rememberKoinModules

val checkoutModule = module {
factory<CheckoutRepository>()
viewModel<CheckoutViewModel>()
}

@OptIn(KoinExperimentalAPI::class)
@Composable
fun CheckoutScreen() {
rememberKoinModules(unloadOnForgotten = true) { listOf(checkoutModule) }

val viewModel = koinViewModel<CheckoutViewModel>()
}

The lambda returns the modules to load. Koin loads them into the Koin instance of the composition the first time CheckoutScreen is composed. Recompositions don't load them again.

Call rememberKoinModules before the koinInject() or koinViewModel() calls that need its definitions.

Unloading​

By default, the modules stay loaded after the Composable leaves the composition. Three parameters control unloading:

ParameterDefaultEffect
unloadOnForgottenunloadModulesUnload when the Composable leaves the composition
unloadOnAbandonedunloadModulesUnload if the composition is abandoned
unloadModulesfalseDefault value for both parameters above
// unload in both cases
rememberKoinModules(unloadModules = true) { listOf(checkoutModule) }

Unloading removes the definitions and drops their single instances. Code that still holds a reference to an instance keeps it, but Koin can no longer resolve that type. Don't unload a module that another screen still uses.

Loading per destination​

Call rememberKoinModules in a navigation destination to load a feature when the user navigates to it:

NavHost(navController, startDestination = HomeRoute) {
composable<HomeRoute> {
HomeScreen()
}
composable<CheckoutRoute> {
rememberKoinModules(unloadOnForgotten = true) { listOf(checkoutModule) }
CheckoutScreen()
}
}

Module styles​

val checkoutModule = module {
factory<CheckoutRepository>()
viewModel<CheckoutViewModel>()
}

Limits​

  • Main thread: modules are loaded synchronously during composition. A large module adds to the time of that frame. To load modules in the background at start, see Lazy Modules.
  • Overrides: a module loaded later wins over an earlier definition of the same type (see Definitions). Unloading it does not restore the earlier definition.
  • Previews: rememberKoinModules needs a running Koin instance. For previews, use KoinApplicationPreview (see Compose Testing).