Given the following: ```private val _selectedUserI...
# coroutines
o
Given the following:
Copy code
private val _selectedUserIds = ConflatedBroadcastChannel<List<Int>>(emptyList())
private val selectedUserIds: Flow<List<Int>> = _selectedUserIds.asFlow()
A
onSaveButtonClick()
method inside the class 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?
k
Should be view state, right? Your VM should reactively drive view state. I would consider current user id to be view state
o
What is view state?
k
Is this is android? or another UI application
o
This is a viewmodel on Kotlin Multiplatform level, so not bounded to any platform
k
Okay
Give you give me a bigger picture of what's going on?
o
The given code above is all in a class named ViewModel
Those two lines are class properties
k
how are values being propagated to the channel?
Is
onSaveButtonClick
in the view or the viewmodel?
o
Viewmodel
Same class
k
Typically, you'd want that to be in the view. In the viewmodel, you'd want something like
handleUSerIds(ids: list<Int>)
and call that viewmodel method from the view when the save button is clicked
your viewmodel shouldn't know anything about the view
o
It doesn't
k
It does if it's got a method declared in it called
onSaveButtonClick
o
the view already calls onSelectUser() of the viewmodel
viewmodel then updates the selectedUserIds with the conflatedbroadcastchannel.offer()
k
okay, and you're trying to get that data back to the view, right?
In which case, you make the flow public and have the view collect the flow in the viewmodel
o
The view already can get the data, it observes the flow. The viewmodel needs to send it to the server on save button click
k
viewmodel then updates the selectedUserIds with the conflatedbroadcastchannel.offer()
Then hook into here when you have the value. When the viewmodel is offering that value to the channel, also do a network request
o
I dont understand, can you be more specific? This would do a network request everytime the selection gets updated
k
Is that not what you're trying to do
?
o
No, only when the save button is clicked
k
If not, then I would maintain an updated list of selected use ids in the viewmodel as well.
Until stateflow comes out, you'd need to provide the data in some other way
flows are stateless. They don't hold an internal value.
o
Check out my initial message, it already shows what I have
I already have a conflatedbroadcadtchannel for the selecteduserids
I guess onSaveButtonClick it should run sendNetworkCall(_selectedUserIds.value) ?
k
okay I understand the question now. Call .value.
collect
is going to keep collecting the flow until it's closed. Also, collect wouldn't produce an element for you until another value is sent to the channel.
o
I understand
Thanks
What would StateFlow do?
k
Stateflow would be similar to Androids livedata
you can post values to it and I believe read its current value
o
I see. So what if the view now wants to read the value of selectedUserIds? Sure it can collect, but let's say the view gets recreated, thus it needing to get the latest value again, what should the view do then?
k
I'm sure you could subclass this flow such that every time it is collected, it re-emits the current value. This may already be implemented, I just haven't read much of the code.
o
You said thay Flow doesn't hold a value, but flow.first() is said to return its current value
k
from the docs
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.
it will suspend until the first value is emitted to the flow
all it does is call collect under the hood and wait for the first value
no state is held in flows
o
So it's like collect, but stopping after it collected its first value
k
correct
Why does he state it otherwise
k
because this is how flow.first will operate on a DataFlow, not a normal flow
o
Yes. counter.first() does compute and return the current value. I'll mention it in the docs.
Ah I see
k
He explicitly will call out that it operates differently than normal flow first
o
So if I want to expose a flow that holds a value, should I just recreate some sort of DataFlow myself, or perhaps copy paste it from the draft?
k
You should stick with what you have
it does largely the same thing
I imagine there's a lot of edge cases which is why this proposal has been around since -September- July
o
But the thing is, this ViewModel will also be used by iOS views, and I assume in some case the iOS view would want to get direct access to the flow state, or am I just worrying about nothing?
k
create a property on your vm which accesses the private channels value
Copy code
val value get() = channel.value