-
-
Notifications
You must be signed in to change notification settings - Fork 771
Description
When using Koin with Jetpack Compose Navigation, passing an existing ViewModel instance via parametersOf() to another ViewModel does not prevent Koin from trying to recreate the dependency ViewModel.
Even though the parameter is explicitly provided, Koin still attempts to resolve the dependency from its definitions, which leads to a crash if that dependency itself requires constructor parameters (e.g. Int).
This makes it effectively impossible to safely pass a shared ViewModel between screens using parameters.
Environment
- Koin version: 4.2.0-beta2
- Android
- Compose Multiplatform
- Navigation3
koinViewModel
Expected Behavior
If a ViewModel is passed via parametersOf(...), Koin should:
- Use the provided instance
- NOT attempt to create a new instance
- NOT resolve its constructor dependencies
(it was working fine in alpha but having issue in beta)
Actual Behavior
Koin ignores the provided instance and tries to create a new one, resulting in:
NoDefinitionFoundException: No definition found for type 'java.lang.Integer'
This happens because Koin attempts to recreate the dependency ViewModel, even though an instance was already passed.
Stacktrace (trimmed)
NoDefinitionFoundException: No definition found for type 'java.lang.Integer'
Could not create instance for '[Factory: EditorSharedViewModel]'
Code
Navigation (Compose)
navigation<EditorScreens.App.AppInfo> {
val sharedViewModel = LocalEditorViewModel.current
val viewModel: AppInfoViewModel = koinViewModel {
parametersOf(sharedViewModel)
}
AppInfoScreen(viewModel = viewModel)
}ViewModel
internal class AppInfoViewModel(
private val editorSharedViewModel: EditorSharedViewModel,
)Koin Module
viewModel {
EditorSharedViewModel(
projectId = get<Int>() // <-- causes crash
)
}
viewModel { (editorSharedViewModel: EditorSharedViewModel) ->
AppInfoViewModel(editorSharedViewModel)
}Problem
Even though EditorSharedViewModel is provided as a parameter, Koin still tries to resolve it from its definition and recreate it, instead of using the passed instance.
This behavior is unexpected and breaks common Compose navigation patterns.
Question
Is this behavior intended?
If so, is there a recommended way to share an existing ViewModel between Compose destinations without Koin trying to recreate it?