Found a longstanding bug in one of my apps because...
# compose
Found a longstanding bug in one of my apps because the LaunchedEffect actually didn't work as expected. I thought this would work
Copy code
LaunchedEffect(key1 = viewModel.appState.items, block = {
but now that I added logs, I can see that even though the size of items changes from 0 to 100, the refresh() never gets called. If I update to
Copy code
LaunchedEffect(key1 = viewModel.appState.items.size, block = {
then everything works correctly. items is defined in the VM as
var items = _mutableStateListOf_<Item>()
I ask because I have cases where the size of items could actually stay the same, but the data was different, and so I'd like to make sure I call refresh() again
You were comparing the same list instance each time. Practically it is equivalent to using
instead of
, as state list doesn't add any magical behavior outside of observation. You probably want to use
as a key instead
What a TIL. Thank you @shikasd
I figured it was instance related, but didn't know the way forward was just to toList() it. lol
What if my list was inside of another class as a stateflow. Example:
val myStateFlow = viewModel.appState.myStateFlow.collectAsState()
or would I do
my models:
Copy code
private val _myAppState: MutableStateFlow<AppState?> = MutableStateFlow(null)
val myAppState: StateFlow<AppState?> = _myAppState

data class AppState(
    val items: List<Long>
so the only thing that's "observable" is the top level appState, so I don't think I should be able to "observe" a list in a LE, can I?
If myStateFlow emits a new value, it'd mean that the list would be a separate instance now afaik. It should just work this way. If the list instance stayed exactly the same, the stateFlow just wouldn't emit anything anyway. The only scenario where this would fail is if you somehow edit values inside the list itself (if you treat the list as mutable), and in such a scenario the stateFlow wouldn't emit in the first place anyway.