[Android] 非同期処理中にアプリバックグラウンドでIllegalStateException発生

スポンサーリンク

背景

以下のようなアプリを作っていた時の話です。

  • ある画面を開いたときにネットワーク(非同期処理中)を行う処理が行われる
  • タイムアウトなどでレスポンスでエラーがあった場合に、ダイアログを表示する

この条件の時に、以下の手順を行うと以下のエラーログが表示されました。

  • 通信中(レスポンスの判定処理が行われる前まで)に、ホームキーなどによりアプリをバッググラウンドに遷移させる
  • タイムアウトで、エラー判定処理が走り、ダイアログを表示しようとする処理が行われる

エラーメッセージ

IllegalStateExceptionが発生しています。

    java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
        at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2080)
        at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2106)
        at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:683)
        at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:637)
        at android.support.v4.app.DialogFragment.show(DialogFragment.java:144)

エラー発生個所

FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit(); // ★★★ここで発生★★★

バッググランドになる際に表示中のFragmentのonSaveInstanceState()が呼ばれて状態が保存された後、トランザクションをコミットしようとしたことでIllegalStateExceptionが発生します。

エラー回避案1

FragmentTransaction.commit()の代わりに
FragmentTransaction.commitAllowingStateLoss()する

デメリットは以下の通り

これは文字通り「画面状態が失われてもいいからコミット」ということで、この時のコミット内容はonSaveInstanceState()で保存されなくなる。
Activityが再生成されたりすると、そのFragmentの状態が正しく復元されなくなるということだ。
これでは弊害も大きくなってしまうし、FragmentManager.popBackStack()のような処理にはそもそもAllowingStateLossなメソッドが存在しない。

参考
https://qiita.com/nein37/items/32613e9acd9558566c5e

FragmentのIllegalStateException回避 - Intelligent Technology's Technical Blog
こんにちは、間藤です。だいぶ間が空いてしまいましたが、またもやAndroidネタです。 前回は、ViewPagerを利用するうえで押さえておきたいポイントを確認してみました。今回は、Fragmentのトランザクションに関するものです。このネタは、「Stack Overflow」の以下の投稿をベースにしています。How ...

エラー回避案2

ハンドラを使って状態の管理を行う

こちらは実は試しておらず、、、
やり方は上記のサイトを参照ください。

コメント

タイトルとURLをコピーしました