반응형
val downloadBooksJob = launch {
downloadBooks()
}
val downloadMoviesJob = launch {
downloadMovies()
}
val downloadSongsJob = launch {
downloadSongs()
}
downloadBooksJob.join()
downloadMoviesJob.join()
downloadSongsJob.join()
// this line will not run until ALL of the downloads complete
위 방식을 이용하는 것 보다 Collection<Job>.joinAll 을 이용하는게 더 보기 좋아진다.
val downloadJobs = listOf(
launch { downloadBooks() },
launch { downloadMovies() },
launch { downloadSongs() }
)
downloadJobs.joinAll()
// this line will not run until ALL of the downloads complete
launch를 호출한다는 것은 나중에 사용하기 위해 호출하는게 아니라 선언 그 시점에 바로 실행된다는 걸 유의할 필요가 있습니다. 각 코루틴은 즉각 실행되고 결과작업이 downloadJobs에 담깁니다.
여기서 더 보기좋은 코드를 만들기 위해 아래와 같은 작업을 할 수 있습니다.
suspend fun awaitAll(vararg jobs: Job) {
jobs.asList().joinAll()
}
awaitAll (
launch { downloadBooks() },
launch { downloadMovies() },
launch { downloadSongs() }
)
// this line will not run until ALL of the downloads complete
상당히 읽기 편해졌습니다.
launch는 실제 작업으로 join을 하지만 joinAll보다는 awaitAll이 가독성이 높기때문에 awaitAll이라고 작성했습니다.
아래 방법처럼 suspend blocks 자체를 전달하는 방향도 있습니다.
suspend fun awaitAll(vararg blocks: suspend () -> Unit) = coroutineScope {
blocks.forEach {
launch { it() }
}
}
suspend fun downloadAll() = coroutineScope {
awaitAll(
::downloadBooks,
::downloadMovies,
::downloadSongs
)
}
suspend fun downloadBooks() {
// download books...
}
suspend fun downloadMovies() {
// download movies...
}
suspend fun downloadSongs() {
// download songs...
}
화면에 프로그레스바 (로딩화면)을 작업할 때 다운로드 작업은 병렬로 하지만, progress bar를 보일지 안 보일지 처리에 해당 코드를 사용하면 매우 심플해지는데요.
viewModelScope.launch {
screenState.update { LOADING }
downloadAll()
screenState.update { READY }
}
제가 개발하는 앱에서도 해당처리가 많지만 이렇게 보기좋게 처리하진 못했습니다. 저도 써봐야겠네요 ㅎㅎ
원본 사이트 :
https://mattrobertson333.medium.com/awaiting-multiple-coroutines-the-clean-way-75469f8df160
반응형
'코틀린' 카테고리의 다른 글
CoroutineScope 의 cancel() 전파 (1) | 2023.05.28 |
---|---|
코틀린 Flows의 소개 (0) | 2022.04.12 |
inline, noinline, crossinline (0) | 2022.02.11 |
코루틴 컨텍스트 전환 (0) | 2021.11.24 |
코루틴 디버깅 (0) | 2021.11.10 |