One thing I never understood: if I'm writing a cla...
# coroutines
c
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
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
So you would recommend something like this?
Copy code
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
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
Thanks