admin管理员组文章数量:1333730
In my application, there are two nested navigations:
- SignedOut
- SignedIn
Every time a user navigates from SignedOut to SignedIn, a new instance of SharedViewModel must be provided.
The same instance of SharedViewModel must be shared between composables inside SignedIn.
The whole point of making SharedViewModel is that the app will be able to cache a massive amount of data between multiple composables avoiding fetching the same data several times.
What I tried:
ViewModel:
@HiltViewModel
class SharedViewModel @Inject constructor(): ViewModel() {
private val instance =
this.toString().substringAfterLast("@")
val data = instance
}
Module responsible for providing SharedViewModel:
@Module
@InstallIn(ViewModelComponent::class)
class SharedViewModelModule {
@Provides
@ViewModelScoped
fun provideSharedViewModel(): SharedViewModel =
SharedViewModel()
}
MainActivity.kt
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val navigationController = rememberNavController()
NavHost(
navController = navigationController,
startDestination = "WelcomeScreen"
) {
navigation(route = "SignedOut", startDestination = "WelcomeScreen") {...}
navigation(route = "SignedIn", startDestination = "HomeScreen") {
composable(
route = "HomeScreen",
content = {
val viewModel = hiltViewModel<SharedViewModel>(it)
}
)
composable(
route = "SecondScreen",
content = {
val viewModel =hiltViewModel<SharedViewModel>(it)
}
)
}
}
}
}
}
What I expected:
I navigate from SignedOut to SignedIn: The same instance of SharedViewModel should be provided to both HomeScreen and SecondScreen composables.
I navigate from SignedIn to SignedOut and back to SignedIn: A completely new instance should be provided for HomeScreen and SecondScreen.
Actual result:
Dagger-hilt provides two different instances for HomeScreen and SecondScreen.
In my application, there are two nested navigations:
- SignedOut
- SignedIn
Every time a user navigates from SignedOut to SignedIn, a new instance of SharedViewModel must be provided.
The same instance of SharedViewModel must be shared between composables inside SignedIn.
The whole point of making SharedViewModel is that the app will be able to cache a massive amount of data between multiple composables avoiding fetching the same data several times.
What I tried:
ViewModel:
@HiltViewModel
class SharedViewModel @Inject constructor(): ViewModel() {
private val instance =
this.toString().substringAfterLast("@")
val data = instance
}
Module responsible for providing SharedViewModel:
@Module
@InstallIn(ViewModelComponent::class)
class SharedViewModelModule {
@Provides
@ViewModelScoped
fun provideSharedViewModel(): SharedViewModel =
SharedViewModel()
}
MainActivity.kt
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
val navigationController = rememberNavController()
NavHost(
navController = navigationController,
startDestination = "WelcomeScreen"
) {
navigation(route = "SignedOut", startDestination = "WelcomeScreen") {...}
navigation(route = "SignedIn", startDestination = "HomeScreen") {
composable(
route = "HomeScreen",
content = {
val viewModel = hiltViewModel<SharedViewModel>(it)
}
)
composable(
route = "SecondScreen",
content = {
val viewModel =hiltViewModel<SharedViewModel>(it)
}
)
}
}
}
}
}
What I expected:
I navigate from SignedOut to SignedIn: The same instance of SharedViewModel should be provided to both HomeScreen and SecondScreen composables.
I navigate from SignedIn to SignedOut and back to SignedIn: A completely new instance should be provided for HomeScreen and SecondScreen.
Actual result:
Dagger-hilt provides two different instances for HomeScreen and SecondScreen.
Share Improve this question edited Nov 20, 2024 at 22:02 Marcel asked Nov 20, 2024 at 21:56 MarcelMarcel 276 bronze badges 1- 1 "the app will be able to cache a massive amount of data between multiple composables avoiding fetching the same data several times" -- often, that is a better task for your repository, rather than a viewmodel. – CommonsWare Commented Nov 20, 2024 at 22:28
2 Answers
Reset to default 1Please have a look at the Android ViewModel Cheatsheet:
As you can see denoted in the orange box, a ViewModel in Hilt by default is scoped to the closest ViewModelStoreOwner
, which in your case is a BackStackEntry
in your NavGraph
. However, you can obtain a ViewModel by its BackStackEntry
and use it in other destinations.
Please try the following code:
composable(
route = "HomeScreen",
content = {
val viewModel = hiltViewModel<SharedViewModel>(it)
}
)
composable(
route = "SecondScreen",
content = {
val homeEntry = remember(backStackEntry) {
navController.getBackStackEntry("HomeScreen")
}
val sharedViewModel = hiltViewModel<ParentViewModel>(homeEntry)
}
)
This case use activityViewModels. It Returns a property delegate to access parent activity's ViewModel, if factoryProducer is specified then ViewModelProvider.Factory returned by it will be used to create ViewModel first time.
First in your build.gradle add
val fragment_version = "1.8.5"
// Kotlin
implementation("androidx.fragment:fragment-ktx:$fragment_version")
In your screen level or fragments
// Access shared ViewModel within composables
val sharedViewModel: MySharedViewModel by activityViewModels()
本文标签:
版权声明:本文标题:android - Sharing single instance of ViewModel between two composables and recreating it when needed - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742325845a2453705.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论