CoroutineContext 인터페이스
CoroutineContext
는 원소나 원소들의 집합을 나타내는 인터페이스임.
Job
, CoroutineName
, CoroutineDispatchers
와 같은 Element
객체들이 인덱싱된 집합임.
- 이는
Map
이나 Set
과 같은 컬렉션이랑 비슷한 개념임.
- 각 Element 또한
CoroutineContext
임.
- 컨텍스트의 지정과 변경을 편리하게 하기 위해
CoroutineContext
의 모든 원소는 CoroutineContext
로 되어 있음.
ex)
launch(CoroutineName("Name1")) { ... }
launch(CoroutineName("Name2") + Job()) { ... }
- 컨텍스트에서 모든 원소는 식별할 수 있는 유일한 Key를 가지고 있고, 각 Key는 주소로 비교가 됨.
public interface Element : CoroutineContext {
/**
* A key of this coroutine context element.
*/
public val key: Key<*>
public override operator fun <E : Element> get(key: Key<E>): E? =
@Suppress("UNCHECKED_CAST")
if (this.key == key) this as E else null
public override fun <R> fold(initial: R, operation: (R, Element) -> R): R =
operation(initial, this)
public override fun minusKey(key: Key<*>): CoroutineContext =
if (this.key == key) EmptyCoroutineContext else this
}
CoroutineName
이나 Job
은 CoroutineContext
인터페이스를 구현한 CoroutineContext.Element
를 구현함.
ex)
fun main() {
val name: CoroutineName = CoroutineName("A name")
val element: CoroutineContext.Element = name
val context: CoroutineContext = element
val job: Job = Job()
val jobElement: CoroutineContext.Element = job
val jobContext: CoroutineContext = jobElement
}
CoroutineContext에서 원소 찾기
CoroutineContext
는 컬렉션과 비슷하기 때문에 get을 이용해 유일한 키를 가진 원소를 찾을 수 있음.
- 원소가 컨텍스트에 있으면 반환되고, 없으면 null이 반환됨.
fun main() {
val ctx: CoroutineContext = CoroutineName("A name")
val coroutineName: CoroutineName? = ctx[CoroutineName] // 또는 ctx.get(CoroutineName)
println(coroutineName?.name) // A name
val job: Job? = ctx[Job]
println(job) // null
}
컨텍스트 더하기
- 두 개의
CoroutineContext
를 합쳐 하나의 CoroutineContext
로 만들 수 있음.
- 다른 키를 가진 두 원소를 더하면 만들어진 컨텍스트는 두 가지 키를 모두 가짐.
CoroutineContext
에 같은 키를 가진 또 다른 원소가 더해지면 Map
처럼 새로운 원소가 기존 원소를 대체함.
비어 있는 코루틴 컨텍스트
CoroutineContext
는 빈 컨텍스트 또한 만들 수 있음.