Let's assume I have a multimodule Jetpack Compose project with feature modules and I want to scope some object instances to features lifecycles. For example, I want to scope AuthRepo
instance to AuthFeature
lifecycle and delete it from memory right after user logged in. Let's also assume that my feature consists of a few composable screens.
So, my MainActivity
looks like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
...
NavHost(navController = navController, startDestination = *AuthFeature graph*) {
navigation(*AuthFeature graph*) {
composable(*First Screen*) { backStackEntry ->
val authGraphEntry = *get authGraphEntry*
val vm = hiltViewModel<AuthViewModel>(authGraphEntry)
...
}
composable(*Second Screen*) { backStackEntry ->
val authGraphEntry = *get authGraphEntry*
val vm = hiltViewModel<AuthViewModel>(authGraphEntry)
...
}
}
*Other feature graph with multiple screens*
}
}
In such case there's no problem: AuthViewModel
, which is common for both screens, is scoped to AuthFeature
graph and I can use Hilt's @ViewModelScoped
annotation while injecting AuthRepo
. So AuthViewModel
will be destroyed after navigating to the other feature (with popping up to the root) and AuthRepo
is going to be destroyed too.
The problem appears when I decide to create one ViewModel per screen. The first screen and the second screen consider to use the same instance of AuthRepo
, however annotating AuthRepo
with @ViewModelScoped
leads to creating two instances of AuthRepo
as I have 2 ViewModels. Annotating it with @Singleton
leads to creating one single instance for the whole app, which is not going to be removed after navigating to another feature.
I came up with 2 ways to solve the issue:
Wrap every feature in an activity and use
@ActivityRetainedScoped
. However I want to use SingleActivity pattern in my project so this solution is not valid for me.Use Dagger and its custom scopes. But I'd like to have a simpler solution without manual component lifecycle handling to keep code cleaner and less error-prone.
On the other hand, I don't want to leave 1 ViewModel per feature because one day it can grow to an enormous amount lines of code. Any ideas? Please correct me if I'm wrong in some of my statements.