harry.singh
03/19/2022, 10:23 PMChannel(Channel.BUFFERED)
as a flow in a Composable function but I'm only ever seeing the latest element and missing all of the elements before the latest one. I've added all of the code here.
I debugged collectAsState
and I'm seeing all of the elements in the produceState
composable function but not in my composable function. Any ideas why this might be happening?Arkadii Ivanov
03/19/2022, 11:02 PMcollectAsState
means the value represents a state, not an event. So there is no need to render intermediate states, only the latest one.lesincs
03/20/2022, 5:21 AMLaunchedEffect
, and then collect your flow directly.harry.singh
03/20/2022, 2:08 PMZach Klippenstein (he/him) [MOD]
03/20/2022, 4:48 PMharry.singh
03/20/2022, 7:53 PMArkadii Ivanov
03/20/2022, 8:05 PMval state = remember { mutableStateOf(...) }
and update it when events are received. The UI will recompose automatically.harry.singh
03/21/2022, 1:03 PMLaunchedEffect
but I'm still seeing only the latest event in that collection as well. Here's my code to collect that flow:
val coroutineScope = rememberCoroutineScope()
LaunchedEffect(key1 = true) {
coroutineScope.launch {
viewModel.eventsFlow.collect {
when (it) {
// Not seeing Event1
is Event1 ->
is Event2 ->
}
}
}
}
The event generation flow is unchanged and Event1 is emitted before Event2Arkadii Ivanov
03/21/2022, 1:28 PMharry.singh
03/21/2022, 1:48 PMThe event might be produced before you actually start collecting, I would check this first.I checked but those events are fired in response to a network response and by the time we receive network response, the composable is already shown on the screen in a fragment, meaning we start collecting it immediately
Arkadii Ivanov
03/21/2022, 1:52 PMPaul Woitaschek
03/21/2022, 1:53 PMharry.singh
03/21/2022, 2:03 PMclass MyViewModel: ViewModel() {
sealed class MyEvent {
object Event1: MyEvent()
object Event2: MyEvent()
}
private val eventsChannel = Channel<MyEvent>(Channel.BUFFERED)
val eventsFlow = eventsChannel.receiveAsFlow()
val state = fetchSomData()
.onEach {
eventsChannel.trySend(Event1)
eventsChannel.trySend(Event2)
}.stateIn(
viewModelScope,
SharingStarted.Lazily,
someInitialValue
)
}
Zach Klippenstein (he/him) [MOD]
03/21/2022, 2:28 PMeventsFlow
collectors at once?viewModel
.Arkadii Ivanov
03/21/2022, 2:35 PMreceiveAsFlow
splits events between multiple subscribers, as per the documentation. You may want to use SharedFlow
.harry.singh
03/21/2022, 2:42 PMDo you ever have a case where there are multipleYep, there was another collector which I thought I had removed. It is working as expected now 🙂collectors at once? (edited)eventsFlow
Also, your launched effect key is wrong, it should beWhy is.viewModel
viewModel
the correct key in this case and true
an incorrect one?Zach Klippenstein (he/him) [MOD]
03/22/2022, 3:43 PMMutableState
to ensure that the effect will be restarted if the dependencies change. In this case, if the thing giving you a ViewModel changes, your effect should restart to re-capture and restart using the new view model.Paul Woitaschek
03/22/2022, 3:58 PMGuilherme Almeida
03/22/2022, 4:05 PMPaul Woitaschek
03/22/2022, 4:06 PMGuilherme Almeida
03/22/2022, 4:09 PM