https://kotlinlang.org logo
#android
Title
# android
o

Orhan Tozan

03/18/2020, 6:52 PM
Given the following viewmodel:
Copy code
class ViewModel {
    val selectedColor: Flow<Color> = ...
    fun onNewColorSelect(newColor: Color) {
        ...
    }
}
How can the
onNewColorSelect
method update the selectedColor flow? With Android, you would use MutableLiveData. How would you solve this problem with Flow?
z

Zach Klippenstein (he/him) [MOD]

03/18/2020, 7:03 PM
It depends how your create your flow. The most common way is to use a
BroadcastChannel
or
ConflatedBroadcastChannel
and convert it into a
Flow
using
asFlow()
. Then you can
offer
values to the channel and they will be emitted.
👍 1
m

magnumrocha

03/18/2020, 7:08 PM
Copy code
private val colorBroadcastChannel = ConflatedBroadcastChannel<Color>

val selectedColor: Flow<Color> = colorBroadcastChannel.asFlow()

fun onNewColorSelect(newColor: Color) {
    colorBroadcastChannel.offer(color)
}
z

Zach Klippenstein (he/him) [MOD]

03/18/2020, 7:10 PM
you probably want to make the channel property private, but yea that’s the idea
👍 1
m

magnumrocha

03/18/2020, 7:11 PM
yes, I've forget that, this is only a sample
o

Orhan Tozan

03/18/2020, 7:11 PM
Really helpful guys, thanks. Is there a reason why one would still expose
selectedColor
as a
Flow<Color>
instead of a
ConflatedBroadcastChannel<Color>
?
m

magnumrocha

03/18/2020, 7:13 PM
to external users of your ViewModel don't manipulate it, offering new values... encapsulation...
o

Orhan Tozan

03/18/2020, 7:13 PM
Ah I see, didn't realise
ConflatedBroadcastChannel<T>
is also write-able
m

magnumrocha

03/18/2020, 7:14 PM
yes, this is only for the encapsulation
z

Zach Klippenstein (he/him) [MOD]

03/18/2020, 7:17 PM
Mostly encapsulation, but also it’s just a nicer API: `Channel`s are effectively a low-level communication primitive and aren’t meant to chain/transform (most/all operators on channels are deprecated). Exposing a
Flow
immediately gives your consumers access to all the flow operators.
m

magnumrocha

03/18/2020, 7:18 PM
yes, also this ☝️
o

Orhan Tozan

03/18/2020, 7:19 PM
Thanks, any reason why I would use
.offer()
over
.send()
?
z

Zach Klippenstein (he/him) [MOD]

03/18/2020, 7:19 PM
send()
is a suspend function, so you can’t call it directly from
onNewColorSelect()
but for
ConflatedBroadcastChannel
, the effect is always the same (
send
never suspends,
offer
always returns
true
)
o

Orhan Tozan

03/18/2020, 7:34 PM
Cool, so does that mean I should expose streams as
Flow<T>
, but should not use the
flow
operator? For example, if I want to initialize the selectedColor Flow with a suspending
getRemoteColor()
function.
m

magnumrocha

03/18/2020, 8:02 PM
flow
creates a
Flow
that completes (or close) when the it hits its finish like:
Copy code
flow<MyObj> {
   doOperation1()
   doOperation2()
   ... // after this line this flow will close
}
this is "like" a hot operator for Flows
this is a good start point
o

Orhan Tozan

03/18/2020, 8:57 PM
Thanks,I try to read throughout it alot. What I still can't wrap my head around is the difference between
.map()
vs
.transform()
.
z

Zach Klippenstein (he/him) [MOD]

03/18/2020, 11:08 PM
map
is a special case of
transform
, if you always want to emit exactly one downstream value for each upstream value:
Copy code
fun <T, R> Flow<T>.map(
  mapper: suspend (T) -> R
): Flow<R> = transform { emit(mapper(it)) }