koin icon indicating copy to clipboard operation
koin copied to clipboard

3.2.0 cant get viewModel

Open frontiertsymbal opened this issue 3 years ago • 8 comments

Hello. Thanks for your library.

I`m using your library with Voyager (https://voyager.adriel.cafe/). I have code to get viewModel from AndroidScreen from Voyager.

` @Composable fun AndroidScreen.getComposeViewModelOwner(): ViewModelOwner = ViewModelOwner.fromAny(getLifecycleOwner())

@OptIn(KoinInternalApi::class) @Composable inline fun <reified T : ViewModel> AndroidScreen.getScreenViewModel( qualifier: Qualifier? = null, owner: ViewModelOwner = getComposeViewModelOwner(), scope: Scope = GlobalContext.get().scopeRegistry.rootScope, noinline parameters: ParametersDefinition? = null, ): T = remember(qualifier, parameters) { scope.getViewModel(qualifier, { owner }, parameters) } `

But after last update (3.2.0) i can`t get scope.getViewModel function (not found) and ViewModelOwner is deprecated. Can you help me solve this issue after update? Thanks

frontiertsymbal avatar May 10 '22 14:05 frontiertsymbal

@arnaudgiuliani what do you suggest as a solution for this issue, I'm had le same problem when trying migrate from v2 -> v3 no scope.viewModel found

serabile avatar May 12 '22 09:05 serabile

I guess we can use something like this:

val ourSession = getKoin().getOrCreateScope("ourSession", named<OurActivity>()).let {
        scope.linkTo(it)
}
private val viewModel by viewModel<OurViewModel> { parametersOf(this) }

serabile avatar May 13 '22 17:05 serabile

ViewModelOwner is deprecated in favor of using directly ViewModelStoreOwner. A ViewModelStoreOwner is an Activity, Fragment, NavBackStackEntry ...

arnaudgiuliani avatar May 17 '22 14:05 arnaudgiuliani

Aligned to the koin internals managed to workaround it like this:

@OptIn(KoinInternalApi::class)
inline fun <reified T : ViewModel> Fragment.viewModelScoped(
    scope: Scope? =  null ,
    noinline parameters: ParametersDefinition? = null,
): Lazy<T> {
    val owner = { this }
    return viewModels(
        ownerProducer = owner,
        factoryProducer = {
            val localScope = scope ?: GlobalContext.get().scopeRegistry.rootScope
            getViewModelFactory<T>(
                owner = owner(),
                qualifier = null,
                parameters = parameters,
                scope = localScope,
            )
        })
}

And if you need it non-lazy just call viewModelScoped.value

So maybe there is a similar workaround with the compose extensions :)

ghost avatar May 20 '22 14:05 ghost

@akoell I've had to tweak your solution a bit to get the desired effect. Here's my variant:

@OptIn(KoinInternalApi::class) inline fun <reified T : ViewModel> Fragment.viewModelScoped( scope: Scope? = null, owner: ViewModelStoreOwner = this, noinline parameters: ParametersDefinition? = null, ): Lazy<T> { val localOwner = { owner } return viewModels( ownerProducer = localOwner, factoryProducer = { val localScope = scope ?: GlobalContext.get().scopeRegistry.rootScope getViewModelFactory<T>( owner = localOwner(), qualifier = null, parameters = parameters, scope = localScope, ) }) }

victorlapin avatar May 23 '22 11:05 victorlapin

it's a problem of passing your scope here?

arnaudgiuliani avatar May 23 '22 11:05 arnaudgiuliani

Actually, I've managed to get the desired result just by linking scopes and setting the correct viewmodel owner.

victorlapin avatar May 23 '22 12:05 victorlapin

@arnaudgiuliani I'm having similar issue, on this 3.1->3.2 migration but on the case that we have an isolated Koin context (https://insert-koin.io/docs/reference/koin-core/context-isolation) on our SDK project.

The only way I could find to make it work was to use internal APIs:

getViewModel(
        scope = isolatedKoin.scopeRegistry.rootScope,
        parameters = parameters
    )

but those got errors and forced to add an @OptIn(KoinInternalApi::class). Is using the internal API the only way to achieve that? Maybe there's something else I missed?

Thanks.

rvp-diconium avatar Aug 09 '22 09:08 rvp-diconium

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 06 '23 11:01 stale[bot]