Skip to content

Bug: Koin recreates ViewModel instead of using provided parameter in Compose Navigation3 #2337

@DevAtrii

Description

@DevAtrii

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions