dewildte
05/04/2019, 6:34 PMView
clicks into Flow<T>
, has anyone done this? What approach did you take? If you think it's a bad idea, why?louiscad
05/04/2019, 6:38 PMawaitOneClick(…)
suspending function and I prefer it that way, looping on it if needed. I actually put that into a library: https://github.com/LouisCAD/Splitties/tree/master/modules/views-coroutinesdewildte
05/04/2019, 6:43 PMlouiscad
05/04/2019, 6:44 PMawaitOneClick()
, simply.dewildte
05/04/2019, 6:45 PMlouiscad
05/04/2019, 6:47 PMdewildte
05/04/2019, 6:47 PMlouiscad
05/04/2019, 6:50 PMwhile
loop where I wait for the click, then react to that, and once that's done, I let the loop interate again if I'm ready to accept further interactions.
All the examples I have are closed source for the company I work for unfortunately, but I plan to use that in future sample code in open source projects. Let me write a dummy example…dewildte
05/04/2019, 6:51 PMFlow<T>
and then passing the flow to an EventBus for collection and redistribution.louiscad
05/04/2019, 6:53 PMwhile (true) {
ui.launchDemoBtn.awaitOneClick()
speakHello() // Suspends until done
}
dewildte
05/04/2019, 6:53 PMlaunch {...}
?louiscad
05/04/2019, 6:54 PMinterface
for the user interface where I expose suspending functions and regular functions, with no dependencies on the platform though. You can call it coroutines enabled MV*dewildte
05/04/2019, 6:57 PMlouiscad
05/04/2019, 7:01 PMCoroutineScope
cancelled when the view hierarchy is destroyed, that's why I made this to not write the boilerplate each time: https://github.com/LouisCAD/Splitties/tree/master/modules/lifecycle-coroutines
If you're in a Fragment
, be sure to use viewLifecycleOwner
.Paul Woitaschek
05/06/2019, 1:04 PMfun View.clicks(): Flow<Unit> {
return flowViaChannel { channel ->
setOnClickListener {
channel.offer(Unit)
}
channel.invokeOnClose {
setOnClickListener(null)
}
}
}
Dominaezzz
05/06/2019, 1:08 PMPaul Woitaschek
05/06/2019, 1:26 PMDominaezzz
05/06/2019, 1:29 PMPaul Woitaschek
05/06/2019, 1:42 PM@FlowPreview
fun main() {
val flow = flowViaChannel<Unit> { channel ->
coroutineScope {
launch {
repeat(10) {
channel.offer(Unit)
}
}
channel.invokeOnClose { println("closed") }
}
}.take(3)
val result = runBlocking {
flow.toList()
}
println("flow emitted $result")
}
Dominaezzz
05/06/2019, 1:57 PMtake(3)
?Paul Woitaschek
05/06/2019, 2:01 PMDominaezzz
05/06/2019, 2:03 PMPaul Woitaschek
05/06/2019, 2:05 PMDominaezzz
05/06/2019, 2:36 PMdewildte
05/06/2019, 7:55 PM@FlowPreview
interface ChannelFlow<T> : SendChannel<T>, Flow<T>
@UseExperimental(FlowPreview::class)
fun <A> channelFlow(
bufferSize: Int = 16
): ChannelFlow<A> {
lateinit var c: SendChannel<A>
val f = flowViaChannel<A>(bufferSize = bufferSize) {
c = it
}
return object : ChannelFlow<A>, SendChannel<A> by c, Flow<A> by f {}
}
@FlowPreview
class ViewFacadeImpl : ViewFacade {
private val channelFlow = channelFlow<ViewEvent>()
override val events: Flow<ViewEvent> = channelFlow
override suspend fun render(viewState: ViewState) {
channelFlow.send(object : ViewEvent {})
}
}
@UseExperimental(FlowPreview::class)
fun <A> channelFlow(
bufferSize: Int = 16
): ChannelFlow<A> {
val eventChannel: Channel<A> = Channel(bufferSize)
val eventFlow: Flow<A> = flow {
for (event in eventChannel) {
emit(event)
}
}
return object : ChannelFlow<A>,
SendChannel<A> by eventChannel,
Flow<A> by eventFlow {}
}