Search code examples
android-jetpack-composekotlin-stateflow

jetpack compose stateflow not refreshing list


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?


Solution

  • 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.