https://kotlinlang.org logo
Title
j

Jan

05/16/2023, 7:50 AM
Hi, what would be a good way to integrate viewModels to decompose? Right now my approach is as follow e.g: • I have a Composable: LoginContent • I have a Component: LoginComponent • Inside LoginComponent I defined a ViewModel like this:
class LoginComponent(
    componentContext: ComponentContext,
) : ILoginComponent, ComponentContext by componentContext, KoinComponent {

    private val _viewModel: LoginViewModel =
        instanceKeeper.getOrCreate {
            getKoin().get()
        }

    override val uiState: StateFlow<LoginUiState> = _viewModel.uiState

    ...
}
• My LoginViewModel extends InstanceKeeper.Instance and has an own coroutine scope which gets cleared 'onDestroy' and is lazily initiated • LoginContent/LoginComponent/LoginViewModel is used within a SlotNavigation So it seems that the lifecycle of the ViewModel is working correctly on Android. E.g. LoginComponent is recreated during orientationChange, but LoginViewModel stays the same. Thats what I want. So good so far. I am just wondering if thats a valid approach. I mean its working, so its valid, but is there a "better" way to do it? Should I instead retain the Component instead of the ViewModel or is that exactly the as described here? Thanks
a

Arkadii Ivanov

05/16/2023, 7:58 AM
That's the correct way, all good. Components should never be retained, unless the tree is intentionally not tied to an activity/fragment (by default it is) and don't capture the activity context
j

Jan

05/16/2023, 9:26 AM
and what about constructor injection for the viewModel? E.G. in my RootComponent I have a slot:
class RootComponent:KoinComponent {

...

childSlot(
    source = slotNavigation,
    handleBackButton = true
) { config, componentContext ->
       LoginComponent(
                componentContext = componentContext
                loginViewModel = getKoin().get()
            )
  }
It seems that the ViewModel is then created on each orientationChange when using this way of injection. So I think I have to use constructor injection in my RootComponentn as well which leads me to the question if its a good approach to put DefaultComponentContext and Components to Koin?
a

Arkadii Ivanov

05/16/2023, 9:37 AM
You should instantiate the ViewModel inside getOrCreate block in your LoginComponent. You can pass a factory to LoginComponent instead, if you want to abstract away the instantiation.
j

Jan

05/16/2023, 9:37 AM
ah, yes. Thats a nicer way ... Thanks