Skip to content

코루틴 컨텍스트

Published: at 오전 08:49

Table of contents

Open Table of contents

CoroutineContext 인터페이스

CoroutineContext에서 원소 찾기

CoroutineContext는 컬렉션과 비슷하기 때문에 get 함수를 사용하여 원소를 찾을 수 있습니다.

fun main() {
  val ctx: CoroutineContext = CoroutineName("A name")

  val coroutineName: CoroutineName? = ctx[CoroutineName]
  println(coroutineName?.name) // A name
  val job: Job? = ctx[Job]
  println(job) // null
}

컨텍스트 더하기

fun main() {
  val ctx1: CoroutineContext = CoroutineName("A name")
  val ctx2: CoroutineContext = Job()

  val ctx3 = ctx1 + ctx2

  val coroutineName: CoroutineName? = ctx3[CoroutineName]
  println(coroutineName?.name) // A name
  val job: Job? = ctx3[Job]
  println(job) // JobImpl{Active}@7b23ec81
}

CoroutineContext에 같은 키를 가진 또 다른 원소가 더해지면 맵처럼 새로운 원소가 기존 원소를 대체합니다.

fun main() {
  val ctx1: CoroutineContext = CoroutineName("A name")
  val ctx2: CoroutineContext = CoroutineName("Another name")

  val ctx3 = ctx1 + ctx2

  val coroutineName: CoroutineName? = ctx3[CoroutineName]
  println(coroutineName?.name) // Another name
}

비어 있는 코루틴 컨텍스트

CoroutineContext는 컬렉션이므로 빈 컨텍스트 또한 만들 수 있습니다. 빈 컨텍스트는 원소가 없으므로, 다른 컨텍스트에 더해도 아무런 변화가 없습니다.

fun main() {
  val ctx1: CoroutineContext = CoroutineName("A name")
  val ctx2: CoroutineContext = EmptyCoroutineContext

  val ctx3 = ctx1 + ctx2

  val coroutineName: CoroutineName? = ctx3[CoroutineName]
  println(coroutineName?.name) // A name
}

원소 제거

minusKey 함수에 키를 넣는 방식으로 원소를 컨텍스트에서 제거할 수 있습니다.

fun main() {
  val ctx1: CoroutineContext = CoroutineName("A name")
  val ctx2: CoroutineContext = Job()

  val ctx3 = ctx1 + ctx2

  val ctx4 = ctx3.minusKey(CoroutineName)

  val coroutineName: CoroutineName? = ctx4[CoroutineName]
  println(coroutineName) // null
}

컨텍스트 폴딩

컨텍스트의 각 원소를 조작해야 하는 경우 다른 컬렉션의 fold와 유사한 fold 메서드를 사용할 수 있습니다.

fun main() {
  val ctx: CoroutineContext = CoroutineName("A name") + Job()

  val result = ctx.fold("Coroutine context elements: ") { acc, element ->
    acc + "\n${element.key}: ${element.value}"
  }

  println(result)
}

코투린 컨텍스트와 빌더

fun CoroutineScope.log(msg: String) {
  val name = coroutineContext[CoroutineName]?.name
  println("$name: $msg")
}

fun main() = runBlocking(CoroutineName("main")) {
  log("Started") // main: Started
  val v1 = async {
   delay(500)
   log("Running async") // main: Running async
   42
  }

  lanuch {
    delay(1000)
    log("Running launch") // main: Running launch
  }

  log("The answer is ${v1.await()}") // main: The answer is 42
}
defaulContext = parentContext + childElement

중단 함수에서 컨텍스트에 접근하기

suspend fun printName() {
  println(coroutineContext[CoroutineName]?.name)
}

suspend fun main() = withContext(CoroutineName("Outer")) {
  printName() // Outer
  launch(CoroutineName("Inner")) {
    printName() // Inner
  }
  delay(100)
  printName() // Outer
}

요약


코틀린 코루틴