Android

Coroutine (1)

YOONJELLY 2023. 12. 6. 17:10

 

코루틴

비동기 경량 스레드

- "Co: 함께" + "routine: 작업 처리단위" = "Coroutine: 어떤 작업을 함께 처리한다."

- 예전에는 ANR 오류를 해결하기 위해 스레드-핸들러나 AsyncTask를 이용했음. 하지만 API 30에서 deprecated되었고 코루틴 이용을 권장하고 있음

- 일반적인 스레드는 자유로운 제어가 힘들고 구현도 복잡하지만, 코루틴은 가볍고 많은 기능을 제공함


CoroutineContext

코루틴 처리를 어떻게 할 것인지에 대한 요소들의 집합

- Dispatcher : 코루틴을 처리할 스레드를 셋팅하고 할당하는 역할

- Job : 생성된 코루틴을 컨트롤 (생명 주기, 부모 자식 관계 정리 및 관리)


Coroutine Dispatcher

- 코루틴을 스레드에 배분하는 역할

- 스레드 풀에서 스레드를 하나 할당해 코루틴을 배당함

- 코루틴은 스레드풀을 생성하지만 직접 제어하지는 않고 오직 Dispatcher를 통해서만 제어 가능

 

Dispatchers 종류

 

1) Dispatchers.Main

- Android Main(UI) Thread에서 Coroutine을 실행하는 Dispatcher

- 반드시 UI와 상호작용하기 위해서만 사용

2) Dispatchers.IO

- File Input/Output, Network IO, Parser 작업에 최적화된 Dispatcher

3) Dispatchers.Default

- 대규모 Sorting, Graphics Rendering 등

- CPU 사용량이 많은 작업에 사용

4) Dispatchers.Unconfined

- 특수한 상황에서 코루틴을 실행 (사용을 권장하지 않음)


CoroutineScope

- 코루틴이 실행되는 범위를 생성

- 다양한 Scope 확장 함수 (= Coroutine Builder)를 이용하여 코루틴을 만듦

 

Coroutine Builder 종류

 

1) launch

- 결과값이 없는 코루틴

- Job 객체를 리턴. 코루틴 관리.

2) async

- 결과값이 있는 코루틴

- Deffered로 감싸서 값 리턴

3) withContext()

- T 반환 (결과값 T를 그대로 반환하는 코루틴)

 

1. 디스패처를 고려하지 않은 코드

CoroutineScope(IO).launch {
	val resultStr = getResultFromApi()
    textView.text = resultStr	// Text를 셋팅하는 부분은 Main Dispatcher에서 진행해야 함.
}

// CRASH 발생

 

2. Coroutine 중복을 통한 해결

// 코루틴 중복으로 인해 가독성이 낮으며 리소스 낭비도 있음

CoroutineScope(IO).launch {
	val resultStr = getResultFromApi()
    
    CoroutineScope(Main).launch {
    	textView.text = resultStr
    }
}

 

3. withContext를 통해 변경

CoroutineScope(IO).launch {
	val resultStr = getResultFromApi()
    
    withContext(Main) {
    	textView.text = resultStr
    }
}

 

4) runBlocking()

- T (코루틴 완료할 때까지 스레드를 점유)

5) actor()

- SendChannel

6) produce()

- ReceiveChannel