Allan Wang
08/21/2019, 8:01 AMoctylFractal
08/21/2019, 8:02 AMcollect, it will stop processingoctylFractal
08/21/2019, 8:03 AMcollect, so you can't cancel it because that's equivalent to just not calling the terminal operation at all -- nothing is running yetAllan Wang
08/21/2019, 8:06 AMoctylFractal
08/21/2019, 8:08 AMisActive, or yield()louiscad
08/21/2019, 8:10 AMval myFlowCollectingCoroutine = launch {
someFlow.collect { // Or any terminal operator
// some cancellable code here
}
}
delay(someDurationOrSomeStuff)
myFlowCollectingCoroutine.cancel()gildor
08/21/2019, 8:10 AMgildor
08/21/2019, 8:11 AMFlow.launchIn(scope) operator which starts flow collection on new coroutine and returns Job that can be cancelled, but it’s essentially the same what Louis showed aboveAllan Wang
08/21/2019, 8:12 AMgildor
08/21/2019, 8:15 AMand have it all cancel once the activity (and the main job) is destroyedYou can do this, just use lifecycleScope to consume flow
gildor
08/21/2019, 8:16 AMsomeFlow.onEach {
doSomethingWith(it)
}.launchIn(activity.lifecycleScope)gildor
08/21/2019, 8:16 AMgildor
08/21/2019, 8:17 AMoctylFractal
08/21/2019, 8:23 AMFlow listen for cancellation somewhere? Otherwise, if doSomethingWith(it) doesn't listen for cancellation, the flow would continue to execute, right?louiscad
08/21/2019, 8:25 AMcollect and emit are one of themoctylFractal
08/21/2019, 8:41 AMgildor
08/21/2019, 8:43 AMgildor
08/21/2019, 8:43 AMoctylFractal
08/21/2019, 8:44 AMisActive check + return from collectgildor
08/21/2019, 8:46 AMoctylFractal
08/21/2019, 8:47 AMoctylFractal
08/21/2019, 8:47 AMgildor
08/21/2019, 8:49 AMoctylFractal
08/21/2019, 8:49 AMdelay is the cancelling part hereoctylFractal
08/21/2019, 8:49 AMThread.sleepgildor
08/21/2019, 8:50 AMoctylFractal
08/21/2019, 8:51 AMemit & collect do not handle cancellation -- but the flow does exit properly if something else doesgildor
08/21/2019, 8:51 AMoctylFractal
08/21/2019, 8:53 AMgildor
08/21/2019, 8:54 AMoctylFractal
08/21/2019, 8:55 AMisActive print false if it's not cancelled?octylFractal
08/21/2019, 8:57 AMfalse, indicating cancellation, but emit proceeds regardless: https://pl.kotl.in/w3xW51_Vblouiscad
08/21/2019, 9:03 AMemit is cancellable 🤔louiscad
08/21/2019, 9:03 AMcollect toogildor
08/21/2019, 9:04 AMoctylFractal
08/21/2019, 9:06 AMcollect variant: https://pl.kotl.in/Fk7r6G-g1octylFractal
08/21/2019, 9:09 AMcollect is cancellable here, or emit in the other snippet, is that they don't behave like other cancellable functions. If `collect`/`emit` was cancellable, it shouldn't print that message. Here's what happens with delay: https://pl.kotl.in/UA0yi3erMgildor
08/21/2019, 9:15 AMoctylFractal
08/21/2019, 9:29 AMPablichjenkov
08/21/2019, 3:17 PMlouiscad
08/21/2019, 3:34 PMemit by itself is non cancellable. collect by itself it not cancellable either, but some operators built on top of it like collectLatest might be.
Interestingly, the terminal toList() operator doesn't seem cancellable as the following snippet executed in a coroutine scope that has just been cancelled prints `a, b`:
println(flow { emit("a"); emit("b") }.toList().joinToString())
This could leak to never cancelling coroutines if the flow is infite and no cancellable suspending functions are called, which would then leak resources.
Is this by design @elizarov?