https://kotlinlang.org logo
Title
c

CLOVIS

06/26/2022, 8:28 AM
One thing I never understood: if I'm writing a class that needs to internally launch coroutines, should the constructor take a
Job
, a
CoroutineScope
, a
CoroutineContext
or something else entirely? The guide is fairly clear on what functions should accept, but I didn't find anywhere it mentions classes.
j

Joffrey

06/26/2022, 8:35 AM
Clearly not a
Job
, it's not the correct abstraction IMO and doesn't allow to customize the dispatcher (e.g. for tests).
CoroutineContext
is nice if your class represents an entity with resources that it would make sense to
close()
- and in this
close()
method you can cancel your custom scope that you created in the class from the given context.
CoroutineScope
would be if you want the caller to manage the scope itself, but I often find it a bit strange to be honest, because it makes it possible that your coroutines are not grouped together and thus cannot be cancelled together without cancelling other unrelated coroutines. That may be ok depending on the use case tough
2
c

CLOVIS

06/26/2022, 8:39 AM
So you would recommend something like this?
class Foo(context: CoroutineContext) {
    private val job = Job(context[Job])
    private val scope = CoroutineScope(job)

    fun close() {
        scope.cancel()
    }
}
However if the passed context doesn't have a
Job
, the scope is now not a part of structured concurrency, right?
j

Joffrey

06/26/2022, 8:41 AM
I was suggesting something like this + a default EmptyCoroutineContext for the context argument. But why the
job
property? Just pass the context directly to the scope builder The
CoroutineScope
factory function creates a job if the context you pass doesn't have one, so structured concurrency still applies here
c

CLOVIS

06/26/2022, 8:43 AM
Thanks