Coroutine Builder 중 Async는 launch와 달리 결과 값을 Deferred<T>의 형태로 반환한다.
반환된 값을 Deferred 인터페이스의 정의 된 await() 메소드를 사용하여 코루틴안에서 결과 값이 만들어질 때 까지 대기하다가 값이 만들어 졌을 때 반환 받을 수 있다.
이 await()메소드를 코루틴 블록 바깥쪽에서 호출하게 되면
"Suspend function 'await' should be called only from a coroutine or another suspend function" 라는 컴파일 에러가 발생한다.
class MainActivity3 : AppCompatActivity() {
private var value: Deferred<Int>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main3)
value = CoroutineScope(Dispatchers.Main).async {
30
}
val t = value?.await()
}
}
에러 문구 그대로 await() 메소드를 사용하기 위해선 Coroutine 블록 안에서 사용하거나, suspend 메소드 안에서 사용해야 한다.
일단 코루틴 블록 안쪽에서 await() 메소드를 사용하면 컴파일 에러가 사라지면서 반환된 값을 사용할 수 있다.
class MainActivity3 : AppCompatActivity() {
private var value: Deferred<Int>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main3)
CoroutineScope(Dispatchers.Main).launch {
value = CoroutineScope(Dispatchers.Main).async {
30
}
val result = value?.await()
}
}
}
두번째로는 suspend 메소드에서 await() 메소드를 사용하는 것인데 suspend 메소드자체도 코루틴 블록 바깥쪽이 아닌 안쪽에서 실행되어야 하며 그렇게 하지 않으면 아까와 동일한 컴파일 에러가 발생한다.
class MainActivity3 : AppCompatActivity() {
private var value: Deferred<Int>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main3)
value = CoroutineScope(Dispatchers.Main).async {
30
}
CoroutineScope(Dispatchers.Main).launch {
val result = awaitTest()
}
}
private suspend fun awaitTest(): Int? {
val t = value?.await()
return t
}
}
위와 같이 suspend 메소드도 Coroutine 블록 안쪽에서 실행 시켜 주면 컴파일에러가 사라지며 반환된 값을 사용할 수 있다.