Issue
I used to use Channel to send out click event from Anko View class to Activity class, however more and more Channel functions are marked as deprecated. So I wanted to start using Flow apis.
I migrated code below:
private val btnProduceChannel = Channel<Unit>()
val btnChannel : ReceiveChannel<Unit> = btnProduceChannel
// Anko
button {
onClick {
btnProduceChannel.send(Unit)
}
}
to:
lateinit var btnFlow: Flow<Unit>
private set
button {
btnFlow = flow {
onClick {
emit(Unit)
}
}
}
I have to mark flow properties as var now which is not so elegant as before. Is this way right? Can I init a Rx Subject like Flow when defining the property?
Edit:
I brought Channel back, then used consumeAsFlow():
private val btnChannel = Channel<Unit>()
// This can be collected only once
val btnFlow = btnChannel.consumeAsFlow()
// Or add get() to make property can be collected multiple times
// But the "get()" can be easily forgotten and I don't know the performance of create flow every access
val btnFlow get() = btnChannel.consumeAsFlow()
// Send event with btnChannel
This seems better than lateinit var one, but any way to get rid of Channel completely? (Though Flow itself like callbackFlow, channelFlow are using channel)
Solution
Although I don't use Anko in my project, I've written this function to use with regular button references, see if it helps you:
fun View.clicks(): Flow<Unit> = callbackFlow {
setOnClickListener {
offer(Unit)
}
awaitClose { setOnClickListener(null) }
}
An example of possible usage is:
button.clicks()
.onEach { /*React on a click event*/ }
.launchIn(lifecycleScope)
UPDATE
As @Micer mentioned in the comments to the original answer, the method Channel#offer has become deprecated in the favour of Channel#trySend method.
The updated version:
fun View.clicks() = callbackFlow<Unit> {
setOnClickListener {
trySend(Unit)
}
awaitClose { setOnClickListener(null)}
}
Answered By - Stanislav Shamilov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.