-
Android Coroutine 사용하기Android 2021. 9. 25. 17:49test
1. Coroutine
Coroutine은
Co(협력) + Routine(규칙적인 작업)의 합성어로
하나의 작업이 끝날 때까지 계속 진행되는 것이 아니라
실행 중간에 다른 작업을 하러 갔다가 다시 돌아와서 작업을 이어서 진행할 수 있다.1.1. Coroutine 은 Thread 가 아니다.
같은 백그라운드 작업을 하는 점에서 비슷하지만
Coroutine은 하나의 작업이라면
Thread는 그 작업을 수행하는 공간이다.
즉 하나의 Thread에서 여러 Coroutine 을 동시에 실행할 수 있다.1.2. 의존성 추가
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5"
1.3. Scope
코루틴은 실행 범위, 제어 범위를 지정할 수 있으며 이 범위를 Coroutine Scpoe 라고 한다.
GlobalScpoe : 프로그램 어디서나 제어, 동작이 가능한 범위
CoroutineScpoe :특정한 목적을 지정하여 제어 및 동작이 가능한 범위CoroutineScope(Dispatchers.IO) CoroutineScope(Dispatchers.Main) CoroutineScope(Dispatchers.Default)
IO : 네트워크 작업이나 DB에 접근하는 등 백그라운드에서 필요한 작업을 수행
Main: 메인스레드 작업으로 UI 갱신이나, Toast 등 View 관련 작업 수행
Default : 무거운 연산 작업 수행2. launch 와 async
코루틴 반환의 여부에 따라 사용된다
2.1. launch
launch는 반환이 없는 job 객체를 반환한다.
launch { for (i in 1..5){ println(i) delay(10) } }
해당 코루틴의 결과를 대기하려면 join 을사용한다.
val a = launch { for (i in 1..5){ println(i) delay(10) } } a.join()
2.2. async
async는 반환값이 있는 Deffered 객체를 반환한다.
val b = async { for (i in 1..5){ println(i) delay(10) } "async 종료" }
해당 코루틴의 결과를 대기하려면 await 을사용한다.
val b = async { for (i in 1..5){ println(i) delay(10) } "async 종료" } b.await()
2.3. runBlocking
fun main(){ val scope = GlobalScope scope.launch { for (i in 1..5){ println(i) } } }
위와 같이 코드를 작성 한 경우 화면에는 출력이 되지 않는다.
그 이유는 코루틴은 스코프 혹은 프로그램이 종료가 되면 같이 종료가 되기 때문에
main 이 종료가 되면서 같이 종료가 된 것이다.
코루틴이 종료될 때까지 메인루틴을 대기하면 화면에 출력된다.fun main(){ runBlocking { launch { for (i in 1..5){ println(i) } } } }
이경우 안드로이드에서 메인스레드 를 오랫동안 대기하면 ANR이 발생하니 주의를 해야 한다.
3. 여러 Dispatchers 의 처리
3.1. 비동기 메서드 생성
suspend fun callApi(): String { return "OK" }
함수 앞에 붙은 suspend는 이 함수가 비동기, 즉 코루틴 안에서 실행하도록 하는 것이다.
만약 코루틴이 아닌 곳에서 사용하려 하면 경고를 출력한다.3.2. 여러 Dispatchers
CoroutineScope(Dispatchers.IO).launch { val result = callApi() textView.text = result }
위와 같이 백그라운드 작업과 UI 작업이 동시에 일어날 때
두 종류의 작업을 처리해야 하는 경우가 생긴다.
물론CoroutineScope(Dispatchers.IO).launch { val result = callApi() CoroutineScope(Dispatchers.Main).launch { textView.text = result } }
위와 같이 코루틴 안에 또 코루틴을 생성하여 처리할 수 있지만
이럴 때 사용하는 withContext가 있다.CoroutineScope(Dispatchers.IO).launch { val result = callApi() withContext(Dispatchers.Main){ textView.text = result } }
4. 네트워크 타임아웃 처리
네트워크 타임아웃 처리는 withTimeoutOrNull로 쉽게 처리할 수 있다.
시간이 경과하면 null 을 반환한다.CoroutineScope(Dispatchers.IO).launch { val result = withTimeoutOrNull(10000) { callApi() } if (result != null) { withContext(Dispatchers.Main){ textView.text = result } } }
'Android' 카테고리의 다른 글
Hilt 사용 (0) 2022.09.05 Android ViewBinding으로 FindViewByid 랑 작별하기 (0) 2021.09.25 Android Retrofit 사용하여 API 호출하기 (0) 2021.09.25 Android Retrofit 인터셉터 사용하기 (0) 2021.09.25 Android Floation Widget 구현하기 (0) 2021.09.25