Coroutine scope is responsible for the structure and parent-child relationships between different coroutines.
トップレベルではDispatchers.Main
を指定し、適宜子コルーチンでバックグラウンドで良い場合にasync(Dispatchers.Default)
としてバックグラウンド化する。
スレッドをブロックする。スコープ内の処理の実行が完了するまでスレッドをブロックする
ViewModelクラスで使える。
ViewModel#onCleared()
のタイミングでキャンセルされる。
アプリケーションの有効期間全体にわたって動作するためGlobalScopeを同一アプリ内で乱用すると不都合が発生したりAndroidのアプリケーションライフサイクルとの間で問題が発生する可能性もあります。
This computation is suspendable: while performing the network requests, it gets "suspended" and releases the underlying thread. When the network request returns the result, the computation is resumed.
launch is used for starting a computation that isn't expected to return a specific result.
launch returns Job, which represents the coroutine. It is possible to wait until it completes by calling Job.join().
This function is designed for parallel decomposition of work.
An async call can return a Deferred or Deferred depending on what the lambda returns (the last expression inside the lambda is the result).
import kotlinx.coroutines.*
fun main() = runBlocking {
val deferred: Deferred<Int> = async {//このラムダ式の中は、スレッドプールの中から選ばれたスレッドで実行される
loadData()
}
println("waiting...")
println(deferred.await())//awaitで、defferdの値が戻ってくるまでメインスレッドの処理を止める
}
/**
* 中断関数
*/
suspend fun loadData(): Int {
println("loading...")
delay(1000L)
println("loaded!")
return 42
}
複数のasync
な処理を開始後、全ての結果が返ってくるまで待つ。
import kotlinx.coroutines.*
fun main() = runBlocking {
val deferreds: List<Deferred<Int>> = (1..3).map {
async {
delay(1000L * it)
println("Loading $it")
it
}
}
val sum = deferreds.awaitAll().sum()//すべての結果が帰ってくるまで待つ
println("$sum")
}
coroutineが実行されるスレッドを指定する
async()
(指定なし) -> If we don't specify one as an argument, then async will use the dispatcher from the outer scope.
async(Dispatchers.Default)
-> システム側でスレッドプールから適宜割り当てる
242 [AWT-EventQueue-0] INFO Contributors - Clearing result
3453 [AWT-EventQueue-0 @coroutine#1] INFO Contributors - kotlin: loaded 47 repos
3763 [DefaultDispatcher-worker-3 @coroutine#3] INFO Contributors - kotlin-examples: loaded 25 contributors
3865 [DefaultDispatcher-worker-3 @coroutine#4] INFO Contributors - ts2kt: loaded 11 contributors
3901 [DefaultDispatcher-worker-2 @coroutine#7] INFO Contributors - kotlin-benchmarks: loaded 7 contributors
3907 [DefaultDispatcher-worker-1 @coroutine#6] INFO Contributors - dokka: loaded 37 contributors
3913 [DefaultDispatcher-worker-3 @coroutine#5] INFO Contributors - kotlin-koans: loaded 44 contributors
4018 [DefaultDispatcher-worker-4 @coroutine#10] INFO Contributors - anko-example: loaded....
/**
* Dispatchers.Default -> バックグラウンドスレッド
* Dispatchers.Unconfined -> メインスレッド
*/
GlobalScope.launch(Dispatchers.Unconfined) {
// 何かしらの処理
}
fun main(args:Array<String>) = runBlocking {
println(1)
GlobalScope.launch {
println(2)
}.join()
println(3)
}
/**
* 実行結果
* 1
* 2
* 3
*/
The major difference with a blocking version is that instead of blocking the thread, we suspend the coroutine:
thread -> coroutine
block -> suspend
launch(Dispatchers.Main) { ... }.join()
is equivalent to withContext(Dispatchers.Main) { ... }