この記事では、簡単のため、CoroutineScope
として GlobalScope
を使用する。
要約
次のコードを実行すると、
GlobalScope.launch(Dispatchers.Main.immediate) {
launch(Dispatchers.Main.immediate) {
Log.i("", "in launch")
}
Log.i("", "after launch")
}
期待に反して、launch
ブロックが先に実行されず、次の順番でログが出力された。
after launch
in launch
仕様かどうかは不明。
前提
メインスレッドにおいて、CoroutineDispatcher
として Dispatchers.Main
を使用して launch
を行う次のようなコードを実行すると、
GlobalScope.launch(Dispatchers.Main) {
Log.i("", "in launch")
}
Log.i("", "after launch")
launch
呼び出しが処理を返してから launch
のブロックが実行されるため、
ログは次のようになる。
after launch
in launch
しかし Dispatchers.Main.immediate
を使用した場合は、
GlobalScope.launch(Dispatchers.Main.immediate) {
Log.i("", "in launch")
}
Log.i("", "after launch")
launch
のブロックが実行されてから launch
呼び出しが処理を返すため、
ログは次のようになる。
in launch
after launch
Dispatchers.Main.immediate
は、メインスレッドで処理を実行するが、既にメインスレッドにいる場合はディスパッチを行わないためである。
参考:
同様に、次のコードも launch(Dispatchers.Main.immediate)
のブロックが先に実行される。
GlobalScope.launch(Dispatchers.Main) {
launch(Dispatchers.Main.immediate) {
Log.i("", "in launch")
}
Log.i("", "after launch")
}
in launch
after launch
本題
次のコードを実行すると、
GlobalScope.launch(Dispatchers.Main.immediate) {
launch(Dispatchers.Main.immediate) {
Log.i("", "in launch")
}
Log.i("", "after launch")
}
期待に反して次の順番でログが出力された。
after launch
in launch
次のように、外側の launch
を Dispatchers.Main
にして、内側の launch
を withContext(Dispatchers.Main.immediate)
で囲んだ場合は
GlobalScope.launch(Dispatchers.Main) {
withContext(Dispatchers.Main.immediate) {
launch(Dispatchers.Main.immediate) {
Log.i("", "in launch")
}
Log.i("", "after launch")
}
}
期待どおり launch
ブロックが先に実行された。
in launch
after launch
どうやら launch(Dispatchers.Main.immediate)
の呼び出し元の直近の launch
も launch(Dispatchers.Main.immediate)
だと、launch
のブロックが先に実行されないようだ。
次のように関数に切り出しても同じ。
@MainThread
fun launchWithImmediate() {
GlobalScope.launch(Dispatchers.Main.immediate) {
Log.i(tag, "in launch")
}
Log.i(tag, "after launch")
}
GlobalScope.launch(Dispatchers.Main.immediate) {
launchWithImmediate()
}
after launch
in launch
そのため、このような関数は呼び出し元によっては期待通りの動作をしない可能性がある。
仕様かどうかは不明(バグのように思える)。
なにかご存じの方がいらっしゃれば、ご教示いただけると幸いです。
/以上