일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- paging
- databinding
- MotionLayout
- MediaSession
- android13
- MediaPlayer
- list
- node.js
- Observable
- Android 13
- SwiftUI Tutorial
- GCP
- 인앱결제
- RxKotlin
- liveData
- mysql
- google play
- SWIFTUI
- node
- Kotlin
- rx
- junit
- PagingLib
- Reactive
- 테스트 자동화
- mvvm
- 동영상
- Animation
- Android
- Koin
- Today
- Total
봄날은 갔다. 이제 그 정신으로 공부하자
Coroutine - part2 본문
이전 글
참고 사이트:
https://developer.android.com/kotlin/coroutines?hl=ko
작업 Timeout 처리하기
비동기 처리의 단점은 비동기 작업을 취소하는데 많은 리소스가 소모된다는데 있습니다.
코루틴에서는 작업 취소를 위해 Job의 cancel() 함수외에도 timeout()함수를 지원합니다.
timeout()함수는 launch{ … }블록이 실행되다가 정해진 시간 이상을 사용한 경우, 해당 블록을 종료해주는 함수이며 사용법은 아래와 같습니다.
Log.d(TAG, "Main Thread - Start")
runBlocking {
val job1 = launch {
withTimeout(500L) {
repeat(100) {
Log.d(TAG, "launch #${it}")
delay(100L)
}
}
}
delay(2000L)
job1.cancelAndJoin()
Log.d(TAG, "end Block")
}
Log.d(TAG, "Main Thread - End")
위 코드는 launch{} 블록이 100번 실행되는 조건 이지만 2sec후에 cancelAndJoin()함수로 인해 launch{} 블록 종료되어야 합니다.
하지만 withTimeout() 함수로 인해 2sec후에 cancelAndJoin() 동작하기 전에 먼저 withTimeout()이 동작하고 작업은 끝나게 됩니다.
출력되는 결과는 아래와 같습니다.
>> Main Thread - Start
>> launch #0
>> launch #1
>> launch #2
>> launch #3
>> launch #4
>> end Block
>> Main Thread - End
launch{...} 블록내 비동기 작업 결과 받기
비동기적 작업이 launch{…} 으로 구분되서 작업되면 좋겠지만 launch{…}블록 내부에서도 비동기 작업이 필요한 경우가 있고 또 블록 내에서 그 결과를 받아서 처리해야 하는 경우가 발생하기도 합니다.
이러한 경우에는 Job을 사용한 처리가 불가능하기 때문에 다른 방법을 사용해야 합니다.
코루틴에서는 async{} 블록을 통해 비동기 작업의 결과를 받아서 처리할 수 있도록 지원합니다.
아래 코드는 GlobalScope.launch{} 블록이 실행되어 “Result Value is”를 출력 한 후에 async 블록에 의해 비동기 작업이 실행되고 Thread는 Log.d(TAG, "${value.await()}”)에서 대기하게 됩니다.
async{} 블록의 작업이 완료되면 value.await()가 호출되게 되고 멈추어 있던 Thread가 깨어나면서 값을 출력하게 됩니다.
GlobalScope.launch {
Log.d(TAG, "Result Value is ")
val value = async {
var total = 0
for(i in 0 ..10){
total += i
delay(200L)
}
total
}
Log.d(TAG, "${value.await()}")
}
async{} 블록은 기본적으로 바로 실행되지만 CoroutineStart.LAZY를 사용하여 원하는 시점에 실행되도록 처리할 수 있습니다.
아래와 같이 처리하게 되면 두 번째 async{} 블록이 먼저 실행되게 됩니다.
GlobalScope.launch {
val value1 = async(start = CoroutineStart.LAZY) {
Log.d(TAG, "async #1")
100
}
val value2 = async(start = CoroutineStart.LAZY) {
Log.d(TAG, "async #2")
200
}
value2.start()
value1.start()
Log.d(TAG, "${value1.await()}")
Log.d(TAG, "${value2.await()}")
}
Channel을 사용해 데이터 전달받기
코루틴은 채널(Channel)이라는 개념을 통해 코루틴에서 생성한 데이터를 또 다른 코루틴에게 전달할 수 있습니다.
아래의 코드는 채널을 사용하여 코루틴 launch{} 블록간 데이터를 공유하는 예제 입니다.
Log.d(TAG, "Main Thread - Start")
runBlocking {
val channel = Channel<Int>()
launch {
for(i in 0 ..4){
delay(1000L)
channel.send(i)
}
channel.close()
}
for(ch in channel){
Log.d(TAG, "channel value: ${ch}")
}
}
Log.d(TAG, "Main Thread - End")
코루틴에서 함수 사용하기
코루틴 블록 내 작업이 많아지는 경우, 이를 별도의 함수로 분리하게 되는데 코루틴 내부에서 실행되는 함수는 suspend로 지정해야 합니다.
아래는 비동기적으로 실행된 코루틴이 완료되어 그 결과를 반환받는 예제 입니다.
suspend 처리되어 있지 않으면 doSomething() 함수에서 await()함수 호출 시 빌드 에러가 발생합니다.
runBlocking {
val value = doSomething()
Log.d(TAG, "${value}")
}
suspend fun doSomething(): Int {
Log.d(TAG, "doSomething")
val value = GlobalScope.async(Dispatchers.IO) {
var total = 0
for(i in 0..10){
total += i
}
total
}
return value.await()
}
'android Tip' 카테고리의 다른 글
Callback Java에서 Kotlin으로… (0) | 2021.01.13 |
---|---|
여러가지 방식으로 List 만들어보기 - OldStyle (0) | 2021.01.11 |
Coroutine - part1 (0) | 2020.12.25 |
android 다양한 주변장치 연동 (NFC, USB) (0) | 2020.12.24 |
Custom 버튼 만들기 (0) | 2020.12.21 |