In my project, I have two fragments.
One is a normal fragment
, and another is a bottomSheetDialogFragment
.
In my normal fragment
, I have a lazyColumn.
I would like to do some settings in the bottomSheetDialogFragment and create a new Hiit
object and put it into my hiitItems
list in my viewmodel
.
The problem is that since my normal fragment
is partially covered by the bottomSheetDialogFragment
, jetpack compose won't re-compose when my list changes.
So I decided to turn to stateFlow
given that it is always firing, and I assume this might cause recomposition. But unfortunately, it did not.
Below are my codes:
// in my viewmodel
// using stateflow to hold the list of hiitItems
private var _hiitItems = MutableStateFlow(mutableListOf(HiitItem()))
val hiitItems = _hiitItems
In my normal fragment
, I'm using composeView to take advantage of jetpack compose
:
setContent {
// get hiitItems
val hiitItems by vm.hiitItems.collectAsState()
...
// lazyColumn
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(hiitItems) // I'm assuming auto refreshing the list here
{
ItemCard(item = it) // ItemCard is just an ordinary composable
}
}
}
In my bottomSheetDialogFragment
, I have a button, whose function is to add the newly created hiitItem into my hiitItems
list, and cause recomposition:
hiitItems.add(newItem)
Any idea why the change in my hiitItems
list is not causing recomposition after I dismiss my bottomSheetDialogFragment?
Solved! Turns out the issue had nothing to do with my MutableStateFlow
.
It was viewModel scope that was causing the failure.
Specifically speaking, my normal fragment
and bottomSheetDialogFragment
each has a distinct viewModel scope
. Therefore, although they did have references to the same viewmodel, the normal fragment
failed to observe the changes caused by the bottomSheetDialogFragment
, which is why the recomposition never fired.
For those who might be suffering from a similar issue as I did, you can check this answer and this article for elabaration!
The takeaway is to make sure that you always acquire the shared viewModel via
val sharedViewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
in different fragments where you want to share the same viewmodel scope.