마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

android 코루틴 foreach 시간

0 추천
A서버에서 suspend fun A() : List<String> 로 받은 결과값을

B서버 인자로 넘겨 suspend fun B(str : String) : List<String>  결과값을 받아 오고 싶은데

val data=mutableListOf<String>()
A().forEach{ it ->
    data.add(B(it))
}
return data

이렇게 처리하니까 시간이.... 어마무시하게 걸리더군요...

(예시는 String이지만 실제는 여러가지 들어있는 List입니다)
한번에 처리가 가능한 방법이 궁금합니다.
dkssudgktpdy (520 포인트) 님이 2022년 4월 29일 질문

1개의 답변

+1 추천
 
채택된 답변

해당 경우도 Coroutine을 이용해서 처리하면 됩니다.  Pararell decomposition이라고 하는 기법입니다. async를 여러개 동시에 실행할 경우 동시에 처리가 되는 특성을 이용해서 아래 같이 처리할 수 있습니다.

fun main() = runBlocking {
        val result = data.map { 
            async { B(it) }
        }.awaitAll()
}

 

이걸 extension function으로 만들어 사용하면 아래처럼 가능합니다.

suspend fun <A, B> Iterable<A>.asyncMap(f: suspend (A) -> B): List<B> = coroutineScope {
    map { async { f(it) } }.awaitAll()
}


fun main() = runBlocking {
    val convertedList = data.asyncMap { B(it) }
}

 

coroutineScope함수는 이 함수를 호출한 Corotuine의 context를 그대로 상속받기 때문에 위처럼 사용할 수 있습니다.

참고로 위 함수를 실행할 때는  Dispatchers.IO나 Distpachters.Default를 사용하시는 걸 권장드려요. 

Edit: 중복함수 제거

spark (227,470 포인트) 님이 2022년 4월 29일 답변
spark님이 2022년 4월 29일 수정
혹시 첫번쨰 예시에서 .map{ it.await() } 이랑
.awaitAll() 이랑 같은 결과와 시간인가요??
둘다 같은 실행시간이라고 보시면 되구요, 그냥 두번째거를 사용하시는게 코드가 더 깔끔합니다. 그리고 실행시간을 측정하고 싶으시면 measureTimeMillis를 사용해서 간단히 확인할 수 있습니다.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.system/measure-time-millis.html
...