반응형

이 게시물은 다음 링크를 참조하여 학습했습니다

 

Coroutine context and dispatchers | Kotlin

 

kotlinlang.org

 

코틀린의 코루틴 — 4.Coroutine Context and Dispatchers

코루틴의 Context와 Dispacher에 대해 알아봅니다.

medium.com

 

1. Coroutine Context

코루틴은 CoroutinContext타입의 값으로 정의된 context에서 실행된다.

CoroutineContext는 다양한 요소들의 집합이다.

대표적으로 Job, Dispatcher가 있다.

 

2. Dispatcher

코루틴 디스패처는 코루틴의 실행을 특정 스레드로 제한하거나, 스레드 풀에 보내거나, 제한 받지 않는 상태로 실행 가능하다.

모든 CoroutineBuilder는 CoroutineContext parameter를 갖는다.

안드로이드에서 기본적으로 제공하는 Dispatcher는 다음과 같다.

Dispatcher.Main : 메인스레드에서 코루틴을 실행하는 디스패처, UI 작업에만 사용해야 한다.

Dispatcher.IO : DB또는 네트워크 IO 작업에 최적화된 디스패처

Dispatcher.Default : CPU를 많이 사용하는 작업을 하는데 최적화된 디스패처(정렬 or 파싱 등 무거운 작업)

 

3. Jumping between threads

import kotlinx.coroutines.*

fun main(){
    newSingleThreadContext("Ctx1").use { ctx1 ->
        newSingleThreadContext("Ctx2").use { ctx2 ->
            runBlocking(ctx1) {
                println("Started in ctx1")
                withContext(ctx2){
                    println("Working in ctx2")
                }
                println("Back to ctx1")
            }
        }
    }
}

하나는 명시적으로 지정된 context의 runBlocking을 사용하고, 다른 하나는 동일한 코루틴에 머무르면서 코루틴의 context를 변경하기 위해 withContext를 사용했다.

 

위 코드는 아래 결과를 출력한다.(디버깅 옵션 적용했을 때)

[Ctx1 @coroutine#1] Started in ctx1
[Ctx2 @coroutine#1] Working in ctx2
[Ctx1 @coroutine#1] Back to ctx1

 

4. Job in the context

코루틴의 Job은 context의 일부로서 coroutineContext[Job] 식을 사용하여 검색할 수 있다.

import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
    println("My job is ${coroutineContext[Job]}")
}

 

위 코드는 아래 결과를 출력한다.

My job is "coroutine#1":BlockingCoroutine{Active}@6d311334

 

핵심은 Job은 CoroutineContext에 포함된다는 점!

 

5. Context 요소 결합

CoroutineContext에서 여러 요소를 정의해야 할 때 +연산자를 활용할 수 있다.

import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
    launch(Dispatchers.Default + CoroutineName("test")) {
        println("I'm working in thread ${Thread.currentThread().name}")
    }
}

 

위 코드는 아래 결과를 출력한다.

I'm working in thread Default Dispatcher-worker-1 @test#2

 

6. CoroutineScope

라이프 사이클이 있는 객체의 컨텍스트에서 비동기 작업을 수행할 때 memory leak을 막기 위해 라이프사이클과 함께 코루틴을 종료해줘야 한다.

수동으로 context와 job을 조작할 수도 있지만, 이를 위한게 바로 CoroutineScope이다.

CoroutineScope 인스턴스는 CoroutineScope() 또는 MainScope() factory 함수에 의해 생성된다.

CoroutineScope()는 범용적인 scope를 생성,

MainScope() 는 UI 애플리케이션을 위한 scope를 생성하고 Dispatcher.Main을 사용한다.

import kotlinx.coroutines.*

class Activity{
    private val mainScope = CoroutineScope(Dispatchers.Default)

    fun destroy(){
        mainScope.cancel()
    }

    fun doSomething(){
        repeat(10) { i ->
            mainScope.launch {
                delay(( i + 1 ) * 200L)
                println("Coroutine $i is done")
            }
        }
    }
}

fun main() = runBlocking<Unit> {
    val activity = Activity()
    activity.doSomething()
    println("Launched coroutines")
    delay(500L)
    println("Destroying activity!")
    activity.destroy()
    delay(3000L)
}

 

++ 안드로이드는 lifecycle이 있는 모든 엔터티에서 coroutine scope에 대한 first-party를 지원한다.

 

수명 주기 인식 구성요소와 함께 Kotlin 코루틴 사용  |  Android 개발자  |  Android Developers

수명 주기 인식 구성요소와 함께 Kotlin 코루틴 사용 Kotlin 코루틴은 비동기 코드를 작성할 수 있게 하는 API를 제공합니다. Kotlin 코루틴을 사용하면 코루틴이 실행되어야 하는 시기를 관리하는 데

developer.android.com

 

반응형

+ Recent posts