async — KotlinのCoroutine Builderで、コルーチンを起動し、非同期操作の結果を取得するためのDeferred<T>オブジェクトを返します。asyncは複数のタスクを並列に実行し、await()を通じて結果をまとめることができます。JetBrainsのガイド(2024)によると、asyncはコルーチンにおける並列計算を組織するのに最適な方法です。
まとめ
async — CoroutineScopeの拡張関数で、結果を返すコルーチンを作成します。launchとは異なり、asyncはDeferred<T> — 将来の値を表すオブジェクトを返します。asyncで起動されたコルーチンは他のコルーチンと並行で実行され、計算を並列化できます。
asyncは、非同期操作の結果が後続処理に必要な場合に使用されます:複数のソースからのデータ読み込み、コレクションのバッチ処理、複数のAPIへの並列リクエストなどです。Deferredは即座に作成され、コルーチンが完了すると結果が利用可能になります。
import kotlinx.coroutines.*
suspend fun String.delayedValue(): String {
delay(1000L)
return this
}
fun main() = runBlocking {
val deferred: Deferred<String> = async { "Hello".delayedValue() }
println(deferred.await())
}
asyncのシグネチャはlaunchと同じです:同じCoroutineContext、CoroutineStartパラメータ、そしてsuspendブロックです。違いは戻り値のタイプです — Jobの代わりにDeferred<T>を返します。ただしTはブロックの最終式が返す結果のタイプです。
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>
Deferred<T> — Jobを継承し、await()、getCompleted()、getCompletionExceptionOrNull()メソッドを追加するインタフェースです。await()はsuspend関数で、コルーチンまたは他のsuspend関数の内部でのみ呼び出せます。getCompleted()は非ブロックングメソッドで、コルーチンがまだ完了していない場合は例外をスローします。
asyncの主な利点は、タスクを並列に実行できることです。それぞれの操作を順番に待つのではなく、asyncはコルーチンを同時に起動し、総時間を最も長い操作の所要時間に縮短します。
タイピカルなシナリオ — 三つの並列asyncリクエストでユーザープロフィール、設定、注文履歴を読み込むことです。すべてが完了すると、結果が1つのデータモデルにまとめられます。
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
val profile = async { api.getProfile(userId) }
val settings = async { api.getSettings(userId) }
val orders = async { api.getRecentOrders(userId) }
Dashboard(
profile = profile.await(),
settings = settings.await(),
orders = orders.await()
)
}
coroutineScope関数はチャイルドコルーチンを起動し、結果を返す前に完了を待ちます。ブロック全体が順番ではなく並列に実行されます。
Deferredは結果を取り扱うための複数のメソッドをサポートしています。await()に加え、状態の確認、完了値の取得、Kotlin Coroutinesのユーティリティ関数を介して複数のDeferredをまとめることができます。
| メソッド | 説明 | Suspend? |
|---|---|---|
| await() | 結果を得られるまでコルーチンを一時停止する | はい |
| getCompleted() | コルーチンが完了していれば結果を返す | いいえ |
| getCompletionExceptionOrNull() | エラー時に例外またはnullを返す | いいえ |
| isCompleted | コルーチンが完了したか確認する | いいえ |
Deferredのリストをまとめるには、awaitAll()を使用します — この関数はコレクション内のすべてのDeferredが完了するまで実行を一時停止します。ひとつでもエラーで完了した場合、awaitAll()は例外をスローします。
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
return coroutineScope {
val deferreds = requests.map { async { it() } }
deferreds.awaitAll()
}
}
asyncとlaunchの選択は、コルーチンの結果が必要かどうかによります。launchはJobを返し、fire-and-forget操作に適しており、asyncはDeferredを返し、データを返すタスクに使用されます。構文とパラメータは同じです。
重要なルール:fire-and-forgetにasyncを使用しないでください。コルーチンの結果が不要な場合はlaunchを使用します。asyncはDeferredの作成によりオーバーヘッドが生じ、そのようなシナリオでは試当ではありません。
Androidでは、asyncはViewModelやUseCases内の並列操作に使用されます。タイピカルなシナリオ:プロフィールとニュースフィードの同時読み込み、複数の天気予報サービスからの天気取得、サーバーとのバッチデータ同期などがあります。
class HomeViewModel : ViewModel() {
fun loadHomeScreen() {
viewModelScope.launch {
val userData = async(Dispatchers.IO) { repository.getUserData() }
val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
val notifications = async(Dispatchers.IO) { repository.getNotifications() }
val state = HomeState(
user = userData.await(),
news = newsFeed.await(),
unread = notifications.await()
)
_uiState.update { state }
}
}
}
エラーをアイソレートするために、asyncのグループをcoroutineScopeまたはsupervisorScopeで囲むことが推奨されます。supervisorScopeは一つが失敗しても他のasyncコルーチンが続行できます — 非クリティカルな操作に便利です。
よくある質問
できますが意味がありません。await()なしのasyncはコルーチンを起動しますが、結果が失われます。結果が不要な場合はlaunchを使用してください — Deferredを作成せず、メモリとパフォーマンスが向上します。
async内の例外はDeferredに保管されます。await()を呼ぶとこの例外がスローされます。スローせずに確認するには、getCompletionExceptionOrNull()を使用します。coroutineScopeを使用すると、エラーがすべてのチャイルドコルーチンをキャンセルします。
awaitAll() — Iterable<Deferred<T>>の拡張関数で、すべてのDeferredが完了するまでコルーチンを一時停止します。結果のリストを返します。ひとつでもDeferredが失敗すると、例外をスローして残りをキャンセルします。
はい。asyncはCoroutineScopeの拡張関数で、スコープに結びつくされています。GlobalScope.asyncはライフサイクルに結びつかずにコルーチンを作成します — 無限に実行される可能性があります。AndroidではメモリリークのリスクからGlobalScopeは推奨されません。
数はディスパッチャによります:Dispatchers.IOは最大64スレッドをサポートし、Dispatchers.DefaultはCPUコア数までサポートします。バッチ操作には、SemaphoreまたはawaitAllとの組み合わせでmapNotNullを使用して並列度を制限します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。