非同期処理とFragment

なんか非同期処理してそれが終わったらFragmentを生成してFragmentManagerに追加するみたいな処理するときってあれですよね。
onSaveInstanceStateの後にやってしまうと怒られますよね。
それ回避用のユーティリティークラス作ってみたのでメモ書きです。
Android Architecture Componentslifecycleを使用します。

import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.OnLifecycleEvent

interface IOnActiveRunner {
    fun setOwner(owner: LifecycleOwner)
    fun runOnActive(handle: () -> Unit)
}

class OnActiveRunner : IOnActiveRunner {
    private val mObserver = OnActiveLifeCycleObserver()
    private var mIsOwnerInitialized = false

    override fun setOwner(owner: LifecycleOwner) {
        if (!mIsOwnerInitialized)
            owner.lifecycle.addObserver(mObserver)
        else throw IllegalStateException()
        mIsOwnerInitialized = true
    }

    override fun runOnActive(handle: () -> Unit) {
        if (!mIsOwnerInitialized) throw IllegalStateException()
        mObserver.run(handle)
    }

    class OnActiveLifeCycleObserver : LifecycleObserver {

        private var isSafe = true
        private val tasks = ArrayList<() -> Unit>()

        fun run(task: () -> Unit) {
            if (isSafe) {
                task()
            } else {
                tasks.add(task)
            }
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        fun onPause() {
            isSafe = false
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        fun onResume() {
            isSafe = true
            tasks.forEach { it() }
            tasks.clear()
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            isSafe = false
        }
    }
}

単純にonPause()が呼ばれたら与えられた関数オブジェクトをリザーブしてonResume()で実行するってだけです。

インターフェースを用意したのは移譲を使ってActivity等で楽に使えるようにするためです。

使うときは…

class HogeActivity : AppCompatActivity(),
        IOnActiveRunner by OnActiveRunner() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //runOnActiveを呼ぶ前にsetOwnerしておく
        setOwner(this)

        //例としてkotlinのcroutine使います
        launch(UI) {
            //async/awaitつかったりとか
            runOnActive { 
                //何かしらの処理
            }
        }
    }
}

みたいな感じで使います。 非同期処理のコールバックでonPause後に呼ばれたくないような処理を行なう時に使う感じです。
最たるものはFragmentTransaction周りの処理だと思います。
他にもonPause後に呼ばれたくないような処理っていくらでもあると思うので使い所は結構多いのでは。

いや、こんなの用意しなくてもそれできるぜって情報があれば教えていただければ幸いです。
commitAllowingStateLossは無しの方向で