Back to Koin

ViewModel

docs/reference/koin-core/viewmodel.md

4.2.25.5 KB
Original Source

Koin provides multiplatform ViewModel support through the koin-core-viewmodel module. This allows you to declare and inject AndroidX ViewModel instances across all Kotlin Multiplatform targets.

Setup

Add the core ViewModel dependency:

kotlin
// build.gradle.kts (commonMain)
implementation("io.insert-koin:koin-core-viewmodel:$koin_version")

For platform-specific injection APIs, add:

kotlin
// Android
implementation("io.insert-koin:koin-android:$koin_version")

// Compose Multiplatform
implementation("io.insert-koin:koin-compose-viewmodel:$koin_version")

Declaring ViewModels

Compiler Plugin DSL

kotlin
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

val appModule = module {
    viewModel<UserViewModel>()
}

Annotations

kotlin
@KoinViewModel
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

Classic DSL

kotlin
val appModule = module {
    // With constructor reference
    viewModelOf(::UserViewModel)

    // With lambda
    viewModel { UserViewModel(get()) }
}

ViewModel with Parameters

Pass parameters at injection time using @InjectedParam:

Compiler Plugin DSL

kotlin
class DetailViewModel(
    @InjectedParam val itemId: String,
    private val repository: DetailRepository
) : ViewModel()

val appModule = module {
    viewModel<DetailViewModel>()
}

Annotations

kotlin
@KoinViewModel
class DetailViewModel(
    @InjectedParam val itemId: String,
    private val repository: DetailRepository
) : ViewModel()

Classic DSL

kotlin
val appModule = module {
    viewModel { params ->
        DetailViewModel(
            itemId = params.get(),
            repository = get()
        )
    }
}

ViewModel Scope

ViewModels that need their own scoped dependencies use the viewModelScope archetype. Dependencies declared inside viewModelScope are tied to the ViewModel's lifecycle.

Compiler Plugin DSL

kotlin
val appModule = module {
    viewModelScope {
        scoped<UserCache>()
        scoped<UserRepository>()
        viewModel<UserViewModel>()
    }
}

Annotations

kotlin
@ViewModelScope
class UserCache

@ViewModelScope
class UserRepository(private val cache: UserCache)

@KoinViewModel
@ViewModelScope
class UserViewModel(
    private val repository: UserRepository
) : ViewModel()

Classic DSL

kotlin
val appModule = module {
    viewModelScope {
        scoped { UserCache() }
        scoped { UserRepository(get()) }
        viewModel { UserViewModel(get()) }
    }
}

:::info Dependencies inside viewModelScope are created when the ViewModel is first accessed and destroyed when the ViewModel is cleared. :::

:::caution Requires the viewModelScopeFactory() option Declaring the ViewModel itself inside viewModelScope { } (so Koin creates its scope automatically) requires enabling the viewModelScopeFactory() option in your Koin configuration:

kotlin
startKoin {
    options(viewModelScopeFactory())
    modules(appModule)
}

Without it, resolving the ViewModel fails with:

No definition found for type 'MyViewModel' on scope '['_root_']'

because the ViewModel is registered under the ViewModel scope archetype, and that scope is only created when the option is enabled. (This is separate from the manual ScopeViewModel pattern, which creates its own scope and does not need the option.) :::

Injecting ViewModels

In Compose (Multiplatform)

Use koinViewModel() in Composable functions:

kotlin
@Composable
fun UserScreen() {
    val viewModel = koinViewModel<UserViewModel>()
    // or with parameters
    val detailVM = koinViewModel<DetailViewModel> { parametersOf("item_123") }
}

In Android

Use by viewModel() delegate in Activity or Fragment:

kotlin
class UserActivity : AppCompatActivity() {
    private val viewModel: UserViewModel by viewModel()

    // With parameters
    private val detailVM: DetailViewModel by viewModel { parametersOf("item_123") }
}

SavedStateHandle

Add SavedStateHandle to your ViewModel constructor - Koin injects it automatically:

kotlin
@KoinViewModel
class MyViewModel(
    private val handle: SavedStateHandle,
    private val repository: UserRepository
) : ViewModel() {

    val userId: String? = handle["userId"]
}
kotlin
val appModule = module {
    viewModel<MyViewModel>()  // Compiler Plugin DSL
    // or
    viewModelOf(::MyViewModel)  // Classic DSL
}

Quick Reference

ApproachModule DeclarationScope Declaration
Compiler Plugin DSLviewModel<MyVM>()viewModelScope { viewModel<MyVM>() }
Annotations@KoinViewModel@KoinViewModel @ViewModelScope
Classic DSLviewModelOf(::MyVM)viewModelScope { viewModelOf(::MyVM) }
PlatformInjection API
ComposekoinViewModel<MyVM>()
Androidby viewModel()

Platform-Specific Features

Next Steps