Lunchbox
Lunchbox

Reputation: 1550

Composable not triggering recomposition

so the issue I'm facing is that when I update a MutableStateFlow value in my ViewModel, the value does not update in the composable:

ViewModel:

private val _dummyData = MutableStateFlow(DummyData())
val dummyData = _dummyData.asStateFlow()

init {
    // Grab the latest data. I've tried grabbing this from onResume() in fragment as well.
    getDummyData()
}

private fun getDummyData() {
    myService.grabData { data ->
        val list = mutableStateListOf<Dummy>()
        data.forEach {
            list.add(it)
        }

        val dummy = DummyData(
            list = list,
        )

        _dummyData.tryEmit(dummy)
    }
}

DummyData:

data class DummyData(
    val list: SnapshotStateList<Dummy> = mutableStateListOf(),
    // View visibility is conditional, based on various factors, adding this here to
    //  show the reason why I'm using it like this
    val displayView: Boolean = false,
)

data class Dummy(val message: String, val url: String)

Fragment:

val dummyData by viewModel.dummyData.collectAsStateWithLifecycle()

// Pass data into composable function

Composable:

LazyRow(
    state = rememberLazyListState(),
    modifier = Modifier,
) {
    // Display list of objects here, they only display on first load.
    // So when I add some break points, I can see the value getting updated in the
    // viewModel, but the change never gets updated here when I change to a different
    // fragment and then navigate back
    val data = dummyData.list
    items(data) { item ->
        // do some stuff, but not relevant to the question, breakpoint at the items(data)
        // to view value of the data, and see that it never gets updated
    }
}

Upvotes: 1

Views: 64

Answers (1)

tyg
tyg

Reputation: 15674

You need to make DummyData and its properties immutable, otherwise it won't work with StateFlows.

That means the list property must be declared like this:

val list: List<Dummy> = emptyList()

If you want to change the list you need to create a new DummyData object with a new list. For example, adding a new element would then look like this:

_dummyData.update {
    it.copy(
        list = it.list + Dummy(...)
    )
}

Upvotes: 1

Related Questions