dave08
01/02/2020, 2:28 PMcallbackFlow
, when should I use cancel(CancellationException("....", e))
and when should I just throw the exception? Is there any difference?Dominaezzz
01/02/2020, 2:43 PMcancel
somewhere internally (the channel has to be released somehow, right?).
I guess calling cancel
is a bit better since you can specify more info about cancellation with a string.dave08
01/02/2020, 2:55 PMCancellationException
there, shouldn't cancel
just recieve its parameters directly...? It seems like that function only takes in a CancellationException
anyways...Adam Powell
01/02/2020, 3:59 PMcallbackFlow
uses a ProducerScope
that is backed by a channel. Your callbackFlow
is the sender and the downstream collector is the receiverclose(cause: Throwable)
, not cancel.cancel
method is in scope as an extension for CoroutineScope
- the scope that you can launch into for parallel decomposition, etc. It's not for reporting errors. That's why it restricts you to CancellationException
only.dave08
01/02/2020, 4:11 PMclose
be called anyways on the channel in such a case?Adam Powell
01/02/2020, 4:15 PMdave08
01/02/2020, 4:33 PMAdam Powell
01/02/2020, 4:40 PMdave08
01/02/2020, 4:41 PMAdam Powell
01/02/2020, 4:41 PMclose(e)
to the `callbackFlow`'s channel instead - that will make the receiver (the flow) resume with the close exceptiondave08
01/02/2020, 4:43 PMcancel
since it closes the channel too, or do you still think close
should be used?Adam Powell
01/02/2020, 4:43 PMclose
. When it comes to channels close
is the sender-side operation, cancel
is the receiver-side operation.cancel
on a channel means, "I cannot, will not receive any more items, let the sender know, and any still lingering in the buffer will be lost."close
means, "here's the end of this sequence of items and possibly a throwable cause if the end-of-sequence is happening for an exceptional reason." All of the items sent to the channel before it will still be received before the close signal is.dave08
01/02/2020, 4:46 PMcancel
on the ProducerScope
not the cancel
on the actual channel...?Adam Powell
01/02/2020, 4:48 PMProducerScope
implements SendChannel
but not ReceiveChannel
, the channel-cancel method isn't even availableCoroutineScope
, which is more often used when cancelling a scope externally, e.g.
val myScope = CoroutineScope(Dispatchers.Main + Job())
// ...
override fun onDestroy() {
myScope.cancel()
}
dave08
01/02/2020, 4:51 PMcallbackFlow
...Flow
doesn't even have access to that scope anyways, so nobody's there to say "I can't receive things anymore" in that particular way.Adam Powell
01/02/2020, 4:53 PMCancellationException
. You immediately end up in cooperative cancellation limbo where isActive
is now false but your code in a cancelled job is still runningtry {
myFlow.collect {
// ...
}
} catch (???) {
// ???
}
what do you want your flow's users to write in the ???
spots?CancellationException
, check the cause
, then re-throw if it's a "real" coroutine cancellation vs. a reported error from your flow, you want them to be able to catch your exception typeclose(e)
gives you thatCancellationException
like that has major additional issues - you might have to unwrap several layers)dave08
01/02/2020, 5:38 PMcatch { }
operator... which probably gives that CancellationException
too with cancel
🤕... whereas with close
it would just give e
.
But you're saying with collect()
the close(e)
(even with the Exception
parameter), wouldn't throw a CancellationException
, it would just throw the e
itself...
This is also a good point, I guess that example in the repo is wrong...Adam Powell
01/02/2020, 5:41 PM