In my ViewModel, when an event listener is trigger...
# coroutines
o
In my ViewModel, when an event listener is triggered:
onUserSelect(userId: Int)
I want it to offer an event to a broadcastchannel named
userSelectEvents: BroadCastChannel<UserSelectEvent>
. The flow
selectedUsers
should depend on this, so I'm probably looking to some kind of building a reducer. This is my idea, is it good?
z
sounds fine, this is a super common pattern
o
So let's say we have the following:
Copy code
class ViewModel {
    val selectedUserIds: Flow<List<Int>> = ...
    fun onUserSelect(userId: Int) {
        ...
    }
}
How would you implement this?
z
What’s the relationship between
onUserSelect
and the lists emitted from
selectedUserIds
? Do newly-selected IDs just get appended to the list?
o
Yes, correct.
z
you’d probably want a
ConflatedBroadcastChannel
, since it lets you access the current value (
value
property). Then you can just get the current list, append, and offer the new list.
o
Ah didn't see the value property. But wouldn't it be cleaner and more declarative if the onUserSelect method did something like selectUserEvents.offer(Event(id)). Then: `selectedUserIds = selectUserEvents.map { userEventsToSelectedUserIds(it) }
z
what does
userEventsToSelectedUserIds
do? how are you accumulating the list of user IDs?
o
Nevermind that, your first suggestion does the trick well.
Let's say we now have a
onSaveButtonClick()
method that sends a network call with the
selectedUserIds
. Should I get it's value by using the
.value
of the
ConflatedBroadcastChannel
or should I launch a coroutine and call
.collect
on the
Flow
?
z
Is this method also in your ViewModel? If so then using the value property would be the most straightforward and communicate your intent clearly. If not, you can get the latest value using
selectedUserIds.first()
.
o
Yes, copy paste from the channel:
Given the following:
Copy code
private val _selectedUserIds = ConflatedBroadcastChannel<List<Int>>(emptyList())
private val selectedUserIds: Flow<List<Int>> = _selectedUserIds.asFlow()
A
onSaveButtonClick()
method should send a network call with the value of selectedUserIds Should I get it's value by using the
.value
of the
ConflatedBroadcastChannel
or should I launch a coroutine and call
.collect()
on the
Flow
? What's the difference?
Allright, didn't know the .first() method on Flow
Wouldn't it make more sense to be named as
.last()
, since it represents the last emitted value?
Copy code
/**
 * The terminal operator that returns the first element emitted by the flow and then cancels flow's collection.
 * Throws [NoSuchElementException] if the flow was empty.
 */
public suspend fun <T> Flow<T>.first(): T {
The doc states here that it returns the first emitted element.