結論
lifecycleScope.launchWhenResumed {
HogeDialogFragment.show(supportFragmentManager, null)
とか
supportFragmentManager.commit {
replace(R.id.container, HogeFragment())
}
}
解説
Can not perform this action after onSaveInstanceState
はその名の通り、ActivityのonSaveInstanceStateメソッドが実行された後に、Fragmentの操作などを行うと発生するクラッシュです。
Rxなどの非同期処理を実行後にダイアログを表示する、などの実装をすると発生します。
では、onSaveInstanceStateはいつ実行されるのかというと
If called, this method will occur after onStop() for applications targeting platforms starting with Build.VERSION_CODES.P. For applications targeting earlier platform versions this method will occur before onStop() and there are no guarantees about whether it will occur before or after onPause().
のように、なんとP以前ではいつ呼ばれるかも明確に決まっていません。
ですが、少なくともライフサイクルがonPauseに入る前、つまりonResumeの時のみ動くようにすれば回避できそうですよね?
そこで、launchWhenResumedを使います。これは、ライフサイクルがonResumeの時のみブロック処理を実行する関数になります。
Launches and runs the given block when the Lifecycle controlling this LifecycleCoroutineScope is at least in Lifecycle.State.RESUMED state.
これを使うことで、P以前、以後関係なく安心して処理を実行することができるようになります。特にFragmentの操作などは、拡張関数などを定義しておくとスッキリ書けるのでオススメです。
おわりに
こんな便利なものを用意してくれて、コルーチンありがとう。コルーチンをすこれ。