LoginSignup
0
0

More than 1 year has passed since last update.

CoroutineScops完全に理解した。

Last updated at Posted at 2021-10-01

完全に理解したからイケてるコードを書こうと思ったら、完全に理解してない箇所が出てきた。調べてもドンピシャに解決する記事がなかったので、自分でイケてるコードを検証したみた。

検証で使ったコード

import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class Hoge(private val context: CoroutineContext) : CoroutineScope {
    override val coroutineContext: CoroutineContext
        get() = context // + Job() or + Job(context.job)

    fun start() {
        launch {
            while(true) {
                println("hoge")
                delay(1_000)
            }
        }
    }
}

suspend fun main() {
    val context = Job() as CoroutineContext
    val hoge = Hoge(context)
    hoge.start()
    val job = hoge.coroutineContext.job

    context.cancel()
    job.join()
}

コメントがある行(#6)をコメント通りに変更すると、Hoge#start()で実行したlaunch()の生死が変わる。

そのまま実行

Hogeクラスのコンストラクタで受け取ったCoroutineContextをそのまま使うので、start()のlaunch()で元のCoroutineContextに内包されるJobから直接子Jobが生成される。
start()では、元のCoroutineContextのJobからlaunch()したときと同じ状況であり、当然元のCoroutineContextをキャンセルすればstart()で生成されたJobは停止し、プログラムは終了する。

+ Job()

Job()の第一引数には親Jobを指定することができるが、何も指定しないと独立したJobが生成される。
また、CoroutineContextのplus()に他のCoorutineContext(Jobもこれのサブクラス)を渡すと、元のCoroutineContextの各要素がもう一方のCoroutineContextが所持している要素によって上書きされる。
そのため、+ Job()をコードに加えると、独立した新しいJobが元のCoroutineContextが持っているJobに取って代わり、よって元のCoroutineContextがキャンセルされてもHogeで開始されたJobは動き続き、コンソールにはhogeが繰り返し表示される。

+ Job(context.job)

親Jobを指定したため、Hoge自体のJobは子Jobであり、start()で生成されたJobは孫Jobになる。
元のCoroutineContextをキャンセルすれば、孫Jobにもキャンセルが伝播しプログラムは終了する。

まとめ

 いつの間にかCoroutineContextとJobのお話になってしまいました。
 適切にCoroutineScopeを分割することで、なにかいいことがある気がする。

 蛇足になりますが、上記のやり方は少しだけ面倒なので、何か特別な操作を必要としない場合はclass Hoge(context: CoroutineContext) : CoroutineScope by CoroutineScope(context + Job(context.job))に書き換えるととても便利です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0