CorotineScopeでの注意点

class HogeFragment() :  Fragment() {
    // 1 
    val scope = lifecycleScope + errorHandler 
    // 2 
    val scope = viewLifecycleOwner.lifecycleScope + errorHandler
    // 3 
    val scope
        get() = viewLifecycleOwner.lifecycleScope + errorHandler

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        scope.launch {
            while (isActive) {
                delay(500)
                Timber.d(this.toString())
            }
        }
    }
}

1のscopeはFragmentのライフサイクルに応じたスコープなのでHogeFragmentがスタック上に行ってもcancelされない。 なので、Timber.dはFragmentがスタック上に行っても出力され続ける。

2のscopeはFragmentのスタックをPopして再度HogeFragmentが表示された時にはcancel状態になってしまう。 スタック上に行った際にViewのライフサイクルに応じたスコープなのでcancelされるが、scope自体はFragmentのメンバ変数なのでFragmentが破棄されて再生成されない限りは同じインスタンスになっている。 なので、Timber.dは1度目のFragment表示時は動いていて、Fragmentがスタック上へ行った際に止まり、Popしてきても再度動かない。

3のscopeはHogeFragmentがスタック上に行ったらcancelされて、再度表示された時にActive状態になるのでコルーチンが動く。 なので、Timber.dはFragment表示時は動いていて、Fragmentがスタック上へ行った際に止まり、Popしてきたら再度動く。