docs/reference/koin-android/viewmodel.md
This page covers Android-specific ViewModel features. For core ViewModel DSL and multiplatform support, see ViewModel.
ViewModels are architecture components designed to survive configuration changes and manage UI-related data. Koin provides special support for ViewModels with lifecycle-aware injection.
:::info
Multiplatform ViewModel - Koin ViewModel DSL is fully multiplatform via koin-core-viewmodel. For Compose Multiplatform, see Compose ViewModel.
:::
:::warning Important: ViewModels are created against the root Koin scope and cannot access Activity or Fragment scoped dependencies. This prevents memory leaks as ViewModels outlive Activities and Fragments.
Need scoped dependencies in ViewModel? Use ViewModel Scope to create a dedicated scope tied to your ViewModel's lifecycle. :::
val appModule = module {
viewModel<DetailViewModel>()
viewModel<UserViewModel>()
}
@KoinViewModel
class DetailViewModel(
private val repository: DetailRepository
) : ViewModel()
@KoinViewModel
class UserViewModel(
private val userRepository: UserRepository
) : ViewModel()
val appModule = module {
// With constructor reference
viewModelOf(::DetailViewModel)
// With lambda
viewModel { DetailViewModel(get()) }
}
In Activity, Fragment or Service, use:
by viewModel() - lazy delegate propertygetViewModel() - eager fetchclass DetailActivity : AppCompatActivity() {
// Lazy inject ViewModel
private val viewModel: DetailViewModel by viewModel()
// Or eager
// private val viewModel: DetailViewModel = getViewModel()
}
Share a ViewModel between Fragments and their host Activity:
by activityViewModel() - lazy delegate for shared ViewModelgetActivityViewModel() - eager fetchclass WeatherActivity : AppCompatActivity() {
private val weatherViewModel: WeatherViewModel by viewModel()
}
class WeatherHeaderFragment : Fragment() {
// Shared with Activity
private val weatherViewModel: WeatherViewModel by activityViewModel()
}
class WeatherListFragment : Fragment() {
// Same instance as WeatherHeaderFragment
private val weatherViewModel: WeatherViewModel by activityViewModel()
}
class DetailViewModel(
@InjectedParam val itemId: String,
private val repository: DetailRepository
) : ViewModel()
val appModule = module {
viewModel<DetailViewModel>()
}
@KoinViewModel
class DetailViewModel(
@InjectedParam val itemId: String,
private val repository: DetailRepository
) : ViewModel()
val appModule = module {
viewModel { params ->
DetailViewModel(
itemId = params.get(),
repository = get()
)
}
}
class DetailActivity : AppCompatActivity() {
private val itemId: String by lazy { intent.getStringExtra("ITEM_ID")!! }
// Pass parameter at injection
private val viewModel: DetailViewModel by viewModel { parametersOf(itemId) }
}
Add SavedStateHandle to your ViewModel constructor - Koin injects it automatically:
@KoinViewModel
class MyStateViewModel(
private val handle: SavedStateHandle,
private val repository: MyRepository
) : ViewModel()
class MyStateViewModel(
private val handle: SavedStateHandle,
private val repository: MyRepository
) : ViewModel()
val appModule = module {
viewModel<MyStateViewModel>() // Compiler Plugin DSL
// or
viewModelOf(::MyStateViewModel) // Classic DSL
}
class DetailActivity : AppCompatActivity() {
// SavedStateHandle automatically injected
private val viewModel: MyStateViewModel by viewModel()
}
:::info
All stateViewModel functions are deprecated. Use the regular viewModel function - SavedStateHandle is injected automatically.
:::
Scope a ViewModel to a Navigation graph:
class NavFragment : Fragment() {
// Scoped to navigation graph
private val navViewModel: NavViewModel by koinNavGraphViewModel(R.id.my_graph)
}
The ViewModel is:
If your ViewModel needs its own scoped dependencies, use ViewModel Scope:
val appModule = module {
viewModelScope {
scoped<UserCache>()
scoped<UserRepository>()
viewModel<UserViewModel>()
}
}
@ViewModelScope
class UserCache
@ViewModelScope
class UserRepository(private val cache: UserCache)
@KoinViewModel
@ViewModelScope
class UserViewModel(
private val repository: UserRepository
) : ViewModel()
For advanced use cases, Koin provides lower-level APIs:
// From ComponentActivity or Fragment
val viewModel = viewModelForClass(
clazz = MyViewModel::class,
qualifier = null,
owner = this,
key = null,
parameters = { parametersOf("param") }
)
Add the compat dependency:
implementation "io.insert-koin:koin-android-compat:$koin_version"
Use ViewModelCompat static methods:
MyViewModel viewModel = ViewModelCompat.getViewModel(this, MyViewModel.class);
| Action | Code |
|---|---|
| Declare ViewModel | viewModel<MyVM>() / @KoinViewModel |
| Inject in Activity/Fragment | by viewModel() |
| Share with Activity | by activityViewModel() |
| Pass parameters | by viewModel { parametersOf(id) } |
| Navigation graph scope | by koinNavGraphViewModel(R.id.graph) |
| With SavedStateHandle | Just add to constructor |