-
[ 코틀린 ] 코루틴2 : Coroutine 사용하기 - 기초Android & Kotlin 2022. 2. 2. 17:33
코루틴의 개념을 먼저 이해하고 싶으시다면
아래 게시글 선행을 추천드립니다.
이번 편에서 코루틴을 사용하는 매우 간단한 방법을 소개합니다.
코루틴에대한 시행착오 및 응용은 다음 포스팅에서 다루겠습니다.
https://easycodediary.tistory.com/95
[ 코틀린 ] 코루틴1 : Coroutine 이해하기
1. 코루틴 이란? 코루틴이란 실행의 지연과 재개를 허용함으로서, 비 선점적 멀티태스킹을 위한 서브루틴을 일반화한 컴퓨터 프로그램 구성요소이다. (위키피디아 참고) 2. 루틴과 코루틴 루틴
easycodediary.tistory.com
인텔리제이에서 코루틴 라이브러리 추가하는 법
https://stackoverflow.com/questions/52522282/using-kotlinx-coroutines-in-intellij-idea-project
Using kotlinx.coroutines in IntelliJ IDEA project
I am trying to learn coroutines and so I fire up IntelliJ and create a scratch file. But when I type in my coroutines I get compiler complaints such as runBlocking is an unresolved reference. So th...
stackoverflow.com
0. 왜 코루틴 인가?
- 비동기적 코드를 기존 동기적를 짜던 방식대로 구현할 수 있다.
- 코루틴 사용전에 비동기 프로그래밍의 콜백이 소개됨.
2. 실행 스레드를 쉽게 지정 및 변경할 수 있다.
- 코루틴을 사용하면 백그라운드 메인등 실행 스레드를 매우 쉽게 변경할 수 있습니다.
출처: https://hanamon.kr/javascript 비동기 프로그래밍을에서 아래 사진과 같은 콜백 지옥을 경험해본신적 있나요?
어떤 작업전에 또 다른 작업이 선행되야하고 이것이 중첩된 결과입니다.
1 . 코루틴 Scope
코루틴은 제어범위 및 실행범위를 지정할 수 있습니다.
(아래 제시하지는 않았지만 플랫폼에 따라 제공하는 Scope가 있을 수 있습니다. ex) 안드로이드 : ViewModelScope )
(runBlocking 또한 )
GlobalScope : 앱이 실행될때 부터 종료될때 까지 실행 (프로그램 어디서나 제어 , 동작이 가능한 기본 범위)
(일반적으로 GlobalScope 상에는 launch 나 async 사용이 권장 되지 않습니다)
// 프로그램이 끝날때 까지 실행될 스코프 생성 GlobalScope.launch { // 백그라운드 스레드로 전환하여 작업 launch(Dispatchers.IO) { } // 메인스레드로 전환하여 작업 launch(Dispatchers.Main) { } }
CoroutineScope : 특정 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위 - 사용자 지정 범위
// 메인 쓰레드에서 동작시킬 스코프 생성 val scope1 = CoroutineScope(Dispatchers.Main) val scope2 = CoroutineScope(Dispatchers.Default) val scope3 = CoroutineScope(Dispatchers.IO) scope1.launch { // 메인 쓰레드에서 동작시킬 내용 } scope2.launch { } scope3.launch { }
2. 코루틴 Context
- 코루틴 작업을 어떠 스레드에서 실행시할 것이지를 결정하는 Dispatcher 가 대표적인 context 요소입니다.
- + 연산을 통해 조합될수 있습니다.
- 주요 요소로 Job 과 Dispatcher , Name 등이 있습니다.
// Job , Diapatcher , Name , Exception 조합 val coroutineContext = Job() + Dispatchers.IO + CoroutineName("context1")+ CoroutineExceptionHandler{context , throwable-> print("${context[CoroutineName]?.name} :: ${throwable.printStackTrace()}")}
Job 객체
- 코루틴의 생명주기를 관리하며 생성된 코루틴 작업들은 부모-자식 관계를 가질 수 있다.
- 규칙1. 부모가 취소되거나 실행 실패시 그 하위 자식들은 모두 취소된다.
- 규칙2. 자식의 실패는 그 부모에 전달되며 부모 또한 실패한다. ( 다른 모든 자식도 취소됨)
- [ job개체 ] . join() 을 통해서 join() 이 포함된 스코프를 멈추고 결과를 기다릴 수 있다.
- [ job개체 ] . cancel() 을 통해서 코루틴을 중단시킬 수 있습니다.
fun main() = runBlocking { val scope3 = CoroutineScope(Dispatchers.IO) val job3 = scope3.launch { // 비동기적으로 실행할 작업 내용 } job3.join() // 작업 내용이 완료될 때까지 runBlocking 스코프를 멈추고 결과를 기다림 job3.cancel() //작업취소 }
Dispatcher
코루틴을 어떤 쓰레드에서 실행할 것 인지를 지정해주는 객체 입니다.
: 코루틴 엘리먼트중 하나로 빌더 내부에 선언하여 코루틴의 실행 스레드를 제한해줄 수 있다.
- Dispatcher.Default
- defaultDispatcher-worker 에서 실행됨
- 코어수에 비례하는 스레드풀에서 수행 (IO 보다 더 적은 스레드를 갖는 스레드 풀)
- IO 에 비해 더 규모 있는 작업에 유리(CPU 많이쓰는 것)
- Dispatcher.Io
- defaultDispatcher-worker 에서 실행됨
- 코어 수보다 훨씬 많은 스레드를 가지는 스레드 풀
- CPU 를 소모하지 않는 작업에 유리 -> 파일 읽기 , 네트워킹
- Dispatcher.Main
- 안드로이드 환경에서만 사용가능
- 안드로이드 에서의 메인 스레드에서 코루틴 실행
- newSingleTreadContext("스레드이름")
- 새로운 스레드를 만들어서 사용할 수 있다.
- 해당 컨텍스트를 통해 동일한 스레드를 사용할 수 있다. -> 공유자원에서 유용
- withoutDispatcher : launch 에 아무 것 도 안넣었을때
- 부모의 컨텍스트에서 수행됨
3. 코루틴 Builder
코루틴 스코프와 컨텍스틀를 이용하여 실제로 코루틴을 실행시키는 함수 입니다.
대표적으로 lanuch 와 async 가 있으며 눈에 띄는 차이점으로는
lanch 는 반환값이 없는 Job 객체를 async 는 반환 값이 있는 Defferd 객체를 반환 합니다.
1. launch
- 즉시실행하며 블록 내의 실행 결과를 반환하지 않는다
- 상위 코드를 블록 시키지 않고(넌블록) 관리를 위한 job 개체를 즉시 반환한다.
- job 객체는 코루틴의 상태를 알려준다.
- join을 통해 상위 코드가 종료되지 않고 완료를 기다리게 할 수 있다.
2. async
- 비동기 호출을 위해 만든 코루틴으로 결과나 예외를 반환한다.
- 실행 결과는 Deffered<T>로 반환
- job 을 상속한 인터페이스로 결과값 수신을 연기함
- 결과 값이 없는 job 에 결과값을 추가하여 확장함
- job.await 은 작업이 완료될 때까지 기다리게 된다.
3. withContext
- async의 await 처럼 결과 객체를 반환함
- async 의 await 를 적용한 것과 같이 결과를 반환할때까지 밖의 블록을 재운다.
코루틴 간단 사용법
1. 코루틴이 실행될 Scope를 결정하여 생성합니다.
(CoroutineScope, GlobalScope, ViewMocelScope(안드로이드 일때) ... )
1. 어떤 쓰레드에서 코루틴을 실행시킬 것인지를 Dispatchers로 정합니다.(Dispatchers.Main, Dispatchers.IO, Dispatchers.Default)
3. launch 또는 async 에 dispatcher 를 추가하고 코루틴을 실행 시킵니다.
viewModelScope.launch(Dispatchers.IO) { //do-something }
[참고]
코루틴 끼리는 비동기적이지만 , 코루틴 내부 코드는 동기적입니다.
'Android & Kotlin' 카테고리의 다른 글
[ Android ] customView의 onDraw 함수 디버깅 기록 (0) 2022.03.04 [ Android ] startActivityForResult deprecated 이유와 대안( Activity Result API) (0) 2022.02.15 [ 코틀린 ] 코루틴1 : Coroutine 이해하기 (0) 2022.02.02 함수형 프로그래밍 with Kotlin (0) 2022.01.20 Thread 에서 UI 접근 (0) 2021.06.14