Currently, if you create a ViewModel using viewModel() composable function, the ViewModel is tied to the activity's ViewModelStoreOwner. This is bad as those ViewModels will only be cleared when the activity's lifecycle is destroyed.
We want this behavior to replicate how fragments do it i.e if you consider a composable screen like a fragment then the ViewModel scoped to composable function should be cleared when the composable's composition is abanded/removed i.e when the fragment's lifecycle is destroyed. This way we won't keep any unused ViewModel instances in the memory.
To make this change, each destination Route will be associated with a LifecycleController class which will manage ViewModel instances scoped to that destination. This also saves state in a bundle from SavedStateHandle when activity's onSaveStateInstance(...) is called & restored when the destination is recreated from the restored backstack after process death.
Usage
class TestRoute : Route {
@Parcelize data class First(...) : TestRoute()
@Parcelize data class Second(...) : TestRoute()
}
class TestViewModel : ViewModel()
@Composable
fun Main() {
...
navigator.Setup(...) { dest ->
when(dest) {
is TestRoute.First -> {
val viewModel = viewModel<TestViewModel>() // <-- Scoped to TestRoute.First
...
}
is TestRoute.Second -> {
val viewModel = viewModel<TestViewModel>() // <-- Scoped to TestRoute.Second
...
}
}
}
}
Support for dagger-hilt
The PR provides an additional artifact to support the creation of ViewModel which is annotated using @HiltViewModel. Through this one can create an instance of ViewModel using hiltViewModel() composable function.
@HiltViewModel
class TestViewModel @Inject constructor(savedStateHandle: SavedStateHandle) : ViewModel()
@Composable
fun Main() {
...
val viewModel = hiltViewModel<TestViewModel>()
}
Additional Changes
Breaking: The signature of ComposeNavigator.Setup(...) is changed as some parameters are reordered.
Proposed
Targeting: (#15)
Currently, if you create a ViewModel using
viewModel()
composable function, the ViewModel is tied to the activity'sViewModelStoreOwner
. This is bad as thoseViewModel
s will only be cleared when the activity's lifecycle is destroyed.We want this behavior to replicate how fragments do it i.e if you consider a composable screen like a fragment then the
ViewModel
scoped to composable function should be cleared when the composable's composition is abanded/removed i.e when the fragment's lifecycle is destroyed. This way we won't keep any unusedViewModel
instances in the memory.To make this change, each destination
Route
will be associated with aLifecycleController
class which will manageViewModel
instances scoped to that destination. This also saves state in a bundle fromSavedStateHandle
when activity'sonSaveStateInstance(...)
is called & restored when the destination is recreated from the restored backstack after process death.Usage
Support for
dagger-hilt
The PR provides an additional artifact to support the creation of
ViewModel
which is annotated using @HiltViewModel
. Through this one can create an instance of ViewModel usinghiltViewModel()
composable function.Additional Changes
ComposeNavigator.Setup(...)
is changed as some parameters are reordered.