•
2장에서는 안드로이드 UI 스레드에서 네트워크를 요청하면 블로킹이 발생하여, 네트워크에서 코루틴을 사용하고 결과만 UI 스레드에서 합쳐서 쓰는 것을 익혔음
•
3장에서는 두가지 유형의 비동기 작업
◦
Job
◦
Deferred
•
비동기 함수의 쉽게 나눠볼 수 있는 두가지
◦
결과가 없는 비동기 ⇒ job
▪
로그를 기록하고 전송하는 것을 백그라운드 작업으로 하는데, 이것이 완료되고 있는지 여부는 검사하지 않는다.
•
물론 큐에 일정 수준 이상 찬것을 노티받기는 함
◦
결과를 반환하는 비동기 ⇒ deferred
▪
결과를 활용해야되는 경우
•
여러 상태정보를 가져올때
◦
물론 두가지 경우다 예외가 발생하거나, 해당작업이 필요하지 않을때 취소를 할 수 있음
•
Job
◦
fire and forget
▪
예외가 발생하지 않는한 대기하지 않는다
fun main(args: Array<String> = runBlocking {
val job = GlobalScope.launch {
}
}
Kotlin
복사
◦
launch 를 사용해 잡을 생성함 or Job()
▪
JobSupport 구현체를 사용
◦
예외처리
▪
Job 내부에서 발생한 예외는 Job을 생성한 곳까지 전파됨
•
현재 스레드에 Uncauht Exception Handler에 예외가 전파됨
◦
라이프 사이클
New → 실행 안된 job
Active → 실행 중인 job
Canceling → 실행 중인 job에서 cancel() 호출되면 취소완료 될때까지의 상태
Cancelled → 취소로 인해 완료된 Job (completed로 분류하기도 함)
Completed → 더 이상 실행이 불가능한 Job
•
Deferred
◦
결과를 반환하는 비동기 작업
▪
promise, futures
▪
연산은 객체를 반환하고, 비동기 작업이 완료될때까지 객체가 비어있음
◦
deferred를 만들려면 async, await으로 만들 수 있음
◦
예외처리
▪
예외를 자동으로 전파하지 않음(Job과 다른점)
▪
결과를 대기할 것으로 예상하기 때문
•
실행이 성공했는지 확인하는 것이 사용자의 몫
▪
예외처리 전파 안됨
val deferred = GlobalScope.async {
}
delay(2000)
Kotlin
복사
▪
예외처리 전파 됨
val deferred = GlobalScope.async {
}
deferred.await()
Kotlin
복사
▪
CoroutineExceptionHandler 를 job 처럼 동일하게 사용가능
•
상태는 한 방향으로만 감
◦
Job이 완료된 경우 다시 실행 불가능
•
안드로이드 예시 ⇒ RSS 여러 피드에서 동시에 읽기
◦
rss 피드 리스트를 등록해서, 각 피드의 정보를 취합하는 앱을 만듬
▪
async, await으로 처음 구성함
◦
피드 url 정보가 잘못되면 await에서 에러를 뿜으며 화면 정지
▪
deferred 예외처리
•
await 대신 join
◦
await는 예외가 바로 전파됨
•
join을 써서 에러가 전파되지 않게 함
feeds.mapTo(requests) {
asyncFetchHeadlines(it, dispatcher)
}
requests.forEach {
it.join()
}
Kotlin
복사
◦
각 피드 응답 합치기
▪
getCompleted() 으로 요청 결과 가져오기
▪
isCancelled → true일땐 getCompeleted()가 에러 전파됨
•
isCancelled가 true인 애들 갯수와 에러만 따로 모아서 보여주기
val failed = requests
.filter { it.isCancelled }
.size
Kotlin
복사
▪
isCancelled → false인 완료된 애들만 getCompleted() 으로 병합해야됨
val headlines = requests
.filter { !it.isCancelled }
.flatMap { it.getCompleted() }
Kotlin
복사