https://kotlinlang.org logo
l

Lilly

09/01/2022, 11:27 AM
I have a really specific use case and I guess I need something to pause and resume the emission of a flow multiple times. To be more concrete: I need to pause a flow to wait for a confirmation from another flow before emitting the next item. Any ideas how to solve this?
j

Javier

09/01/2022, 11:51 AM
That is how suspend works by default
Copy code
suspend fun main() {
     val something = someSuspend()
     … // this will not be executed until someSuspend() ends
}
l

Lilly

09/01/2022, 11:56 AM
I have 2 independent flows. Flow1 has to wait for a specific piece of code of flow2 to be confirmed before emitting
I have adjusted my question, was a bit misleading
j

Javier

09/01/2022, 12:11 PM
I am on mobile but probably a function like
zip
or something similar can help you
c

Casey Brooks

09/01/2022, 2:42 PM
You might consider re-organizing your logic a bit. Rather than having multiple independent flows relying on the state of each other, consider more an an Actor or MVI pattern. You have one job that sends a “message” to be processed. Once that finishes, it sends a message to another, and so on. In your use-case, instead of flow1 doing some processing, then sending a job to flow2, and then waiting for flow2 to complete before resuming flow1, have flow2 send a message to a new flow3 that handles that portion of the logic, passing all necessary context along through the entire pipeline
l

Lilly

09/01/2022, 6:24 PM
@Casey Brooks it is more complicated. Flow2 listen to a bluetooh socket until flow1 is getting canceled (
transformWhile
) while flow1 sends data to the bluetooth socket. It is like ping pong...flow1 send request, flow2 listen to response and every successful request needs to be confirmed by receiving an Acknowledgement byte. flow1 has to wait for this confirmation. I can merge the code together but then I have requesting and receiving logic tightly coupled and that does not representing my current implementation which decouples both in a clean way
p

Paul Woitaschek

09/02/2022, 4:37 AM
You can just loop it if I understand correctly? I.e. while true f1.first() f2.first()
n

Nick Allen

09/02/2022, 6:47 AM
Sounds like you may want something like:
Copy code
coroutineScope {
    val channel2 = flow2.produceIn(this)
    try {
        flow1.collectWhile {
            sendRequest(it)
            handleResponse(channel2.receiveCatching())
        }
    } finally {
        channel2.close()
    }
}
j

Javier

09/02/2022, 8:19 AM
first() is a terminator operator I think, the flow would end when you call it
3 Views