I am using Jetpack compose for my UI rendering. I have Fragment1 and Fragment2. I have a viewModel SharedViewModel which is defined in activity scope.
When I send an update from Fragment2 which is in foreground via SharedViewModel, it is not updating Fragment1 which is in background, which is observing a state object of SharedViewModel.
Activity ->
private val viewModel: SharedViewModel by viewModels { viewModelFactory }
SharedViewModel ->
private val _installedApps = MutableStateFlow(HashMap<String, String>())
val installedApps: StateFlow<Map<String, String>> = _installedApps.asStateFlow()
fun updateInstalledApps(appId: String, params: String) {
_installedApps.update {
it[appId] = params
it
}
}
Fragment1 ->
fun ListScreen(
listViewModel: ListViewModel,
viewModel: SharedViewModel,
onBackButtonClicked: () -> Unit
) {
val state by appListViewModel.appListState.collectAsState()
val context = LocalContext.current
LaunchedEffect(inContextStoreViewModel.installedApps.collectAsState().value) {
appListViewModel.updateInstalledApps(inContextStoreViewModel.installedApps.value)
}
LaunchedEffect(inContextStoreViewModel.networkConnectionState.collectAsState().value) {
if (state.apps.isEmpty()) {
appListViewModel.getApps(appAcquisitionParams, inContextStoreViewModel.launchParamsObject.value)
}
}
// rest of UI which is observing
}
Fragment2 ->
onAddClicked = {
detailViewModel.install(
callBack = {
sharedViewModel.updateInstalledApps(appId, it)
}
)
},
Interestingly, the networkConnectionState is always getting updated correctly in all fragment since it is triggered from activity. Also, this was working fine when navigation graph was used. But with Fragment Transaction, it is causing this issue. Need some input which viewModel concept is getting missed.
StateFlow
is not trigger collectors if updated value has the same link to object. You are update an item in hashmap and return the same StateFlow
. The changes inside complicated structure like map is not be detected. Because will be just compare like StateFlow == StateFlow
. If true, collectors is not fire.
Or create new hashmap every time when updateInstalledApps
called, or use SharedFlow
instead (there is no compare inside).