작업이 재개되는 원리를 살펴보자
suspend fun main() {
println("Before")
// 중단 함수
suspendCoroutine<Unit> { }
println("After")
}
// Before 만 출력됨
suspendCoroutine 함수가 Continuation 객체를 인자로 받음suspend fun main() {
println("Before")
suspendCoroutine<Unit> { continuation ->
println("Before too")
}
println("After")
}
// Before
// Before too
suspendCoroutine 함수는 중단되기 전에 continuation 객체를 사용할 수 있음suspendCoroutine 이 호출된 뒤에는 이미 중단되어 continuation 객체를 사용할 수 없음suspend fun main() {
println("Before")
suspendCoroutine<Unit> { continuation ->
continuation.resume(Unit)
}
println("After")
}
// Before
// After
private val executor =
Executors.newSingleThreadScheduledExecutor {
Thread(it, "scheduler").apply { isDaemon = true }
}
suspend fun delay(timeMillis: Long): Unit =
suspendCoroutine { cont ->
executor.schedule({
cont.resume(Unit)
}, timeMillis, TimeUnit.MILLISECONDS)
}
suspend fun main() {
println("Before")
delay(1000)
println("After")
}
// Before
// 1초 뒤
// After
delay의 동작 방식 (어떻게 멈추고, 어떻게 다시 주도권을 반환하는지 보여주는 코드)delay 함수를 사용하는 모든 코루틴의 전용 스레드가 되어 대기할 때마다 하나의 스레드를 블로킹하지 않음suspendCoroutine을 호출할 때 continuation 객체로 반환될 값의 타입을 지정할 수 있음resume을 통해 반환되는 값은 반드시 지정된 타입과 같은 타입이어야 함suspend fun main() {
val i: Int = suspendCoroutine<Int> { cont ->
cont.resume(42)
}
println(i) // 42
val str: String = suspendCoroutine<String> { cont ->
cont.resume("Some text")
}
println(str) // Some text
val b: Boolean = suspendCoroutine<Boolean> { cont ->
cont.resume(true)
}
println(b) // true
}
resume 함수를 통해 보내줘” 라고 요청 가능suspend fun requestUser(): User {
return suspendCoroutine<User> { cont ->
requestUser {user ->
cont.resume(user)
}
}
}
suspend fun main() {
println("Before")
val user = requestUser()
println(user)
println("After")
}
⇒ 이런 경우 데이터를 반환할 수 없으므로 코루틴이 중단된 곳에서 예외를 발생시켜야 함
suspendCoroutine 함수도 값을 반환하거나 예외를 던짐resumeWithException 이 호출되면 중단된 지점에서 인자로 넣어준 예외를 던짐// 네크워크 관련 예외 발생 예시 코드
suspend fun requestUser() : User {
return suspendCancellableCoroutine<User> { cont ->
requestUser { resp ->
if (resp.isSuccessful) {
cont.resume(resp.data)
} else {
val e = ApiException(
resp.code,
resp.message
)
cont.resumeWithException(e)
}
}
}
}
suspend fun requestNews(): News {
return suspendCancellableCoroutine<News> { cont ->
requestNews(
onSuccess -> { news -> cont.resume(news) },
onError -> { e -> cont.resumeWithException(e) }
)
}
}
중단 함수는 무엇을 중단할까? 🛑