https://kotlinlang.org logo
#coroutines
Title
# coroutines
z

Zhanna Gorelova

06/29/2022, 11:11 AM
Hello! I am a bit confused with the case, how can I cancel the flow job, since in tests sometimes happens that after a 30 seconds the flow is still alive and does println(), but now other test is in processing. Since I pass context without job, there is no job and ensureActive returns true and I can’t cancel the job with flow. And context.cancel() as well cancels job, but there is no such in context. I thought that launch with flow should inherit parents Job, but what if there is no such? Thanks!
Copy code
class CoroutineTest {
    @Test
    fun `test`() = withContext { context ->
        // when
        SomethingWithFlow(context)

        //then
        assertNotNull(context[Job])
    }

    private fun withContext(context: CoroutineContext = <http://Dispatchers.IO|Dispatchers.IO>, block: suspend (CoroutineContext) -> Unit) {
        runBlocking(context) { block(context) }
    }

    class SomethingWithFlow(override val coroutineContext: CoroutineContext) : CoroutineScope {
        private val flow = MutableStateFlow<String>("Initial")

        init {
            launch {
                flow.debounce(30_000L).collectLatest {
                    ensureActive()
                    println(it)
                }
            }
        }
    }
}
n

Nick Allen

06/29/2022, 6:00 PM
If there's no
Job
in
CoroutineScope
, then you have to manage the coroutines individually. This is a rare but expected scenario.
GlobalScope
does not have a
Job
and can not be cancelled. To cancel
collectLatest
, you have to capture the
Job
returned by
launch
and cancel that. The CoroutineScope interface docs recommend that the factory functions like
CoroutineScope()
are used to create an instance. You can use
GlobalScope
where you don't need a cancellable scope (like a process long coroutine in a singleton) and you can use
CoroutineScope()
or
MainScope()
when you do want to cancel the scope because these functions include a
Job
if it's not already there. If you have a scope with the right
Job
(or lack of
Job
), then you can use
+
to create a new scope with the other `ContextElement`s that you want. If I wanted a non-cancellable scope for IO, I'd create it with
GlobalScope + <http://Dispatchers.IO|Dispatchers.IO>
.
🙏 1
4 Views