AndroidとかiOSとかモバイル多め。その他技術的なことも書いていきます。

Kotlin Coroutinesで並列にListの各項目を処理する

coroutineScope {
    list.map { async { updateListItem(it) } }
        .map {
          val updated = it.await()
          ... 
        }
}

最初のmapで処理を走らせてしまうと処理待ちになって逐次実行になる。そのためまず最初のmapですべてのListの項目の処理を遅延実行し、次のmapで各処理の結果を待つ。

ちなみに最初Flowでできないか試したが、Flowはイベントストリームのように逐次実行されるのでListの各項目を並列に処理するのには向いていない。

list.asFlow()
        .map {
            Timber.i("start async ${it.title} start")
            coroutineScope { async { updateListItem(it) } }
        }
        .map {
            Timber.i("start await ${it} start")
            it.await()
        }

とすると

2019-12-17 21:29:55.426 11681-11681/com.phicdy.sample I/Hoge$updateAll$$inlined$map: start async list1 start
2019-12-17 21:29:55.434 11681-11808/com.phicdy.sample I/Hoge$hoge: DefaultDispatcher-worker-3 list1 updateListItem start
2019-12-17 21:29:56.856 11681-11808/com.phicdy.sample I/Hoge$hoge: DefaultDispatcher-worker-3 list1 updateListItem done
2019-12-17 21:29:56.858 11681-11681/com.phicdy.sample I/Hoge$updateAll$$inlined$map: start await DeferredCoroutine{Completed}@d1d861 start
2019-12-17 21:29:56.863 11681-11681/com.phicdy.sample I/Hoge$updateAll$$inlined$map: start async list2 start
2019-12-17 21:29:56.881 11681-11808/com.phicdy.sample I/Hoge$hoge: DefaultDispatcher-worker-3 list2 updateListItem start
2019-12-17 21:29:58.045 11681-11807/com.phicdy.sample I/Hoge$hoge: DefaultDispatcher-worker-2 list2 updateListItem done
2019-12-17 21:29:58.046 11681-11681/com.phicdy.sample I/Hoge$updateAll$$inlined$map: start await DeferredCoroutine{Completed}@ef2999d start

と逐次実行になってしまう。