web-dev-qa-db-ja.com

「IllegalStateException:onSaveInstanceStateの後にこのアクションを実行できない」という例外が発生する

私はLive Androidアプリケーションを持っています、そして市場から私は以下のスタックトレースを受け取りました、そしてなぜアプリケーションコードで起こっていないとしてそれが起こっているのですか

私はFragmentsを使っていません、それでもFragmentManagerのリファレンスがあります。この種の問題を回避するために、誰かがいくつかの隠された事実に光を当てることができるならば:

Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at Android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1109)
at Android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.Java:399)
at Android.app.Activity.onBackPressed(Activity.Java:2066)
at Android.app.Activity.onKeyDown(Activity.Java:1962)
at Android.view.KeyEvent.dispatch(KeyEvent.Java:2482)
at Android.app.Activity.dispatchKeyEvent(Activity.Java:2274)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.Java:1668)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at Android.view.ViewGroup.dispatchKeyEvent(ViewGroup.Java:1112)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.Java:1720)
at com.Android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.Java:1258)
at Android.app.Activity.dispatchKeyEvent(Activity.Java:2269)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.Java:1668)
at Android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.Java:2851)
at Android.view.ViewRoot.handleFinishedEvent(ViewRoot.Java:2824)
at Android.view.ViewRoot.handleMessage(ViewRoot.Java:2011)
at Android.os.Handler.dispatchMessage(Handler.Java:99)
at Android.os.Looper.loop(Looper.Java:132)
at Android.app.ActivityThread.main(ActivityThread.Java:4025)
at Java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:491)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:841)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:599)
at dalvik.system.NativeStart.main(Native Method)  
343
dcool

これは私が今まで遭遇した中で最も愚かなバグです。 FragmentアプリケーションがAPI <11、およびForce Closingに最適に動作しています。 onAPI> 11

Activityの呼び出しで、saveInstanceライフサイクル内でそれらがどのように変化したのかを実際に把握することはできませんでしたが、私はこれをどのように解決したかを示します。

@Override
protected void onSaveInstanceState(Bundle outState) {
    //No call for super(). Bug on API Level > 11.
}

私は.super()を呼び出さないで、すべてうまくいきます。これで時間が節約できると思います。

編集: もう少し調べてみると、これはサポートパッケージの既知の バグ です。

インスタンスを保存してoutStateBundleに何か追加する必要がある場合は、次のようにします。

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
    super.onSaveInstanceState(outState);
}

編集2: Activityがバックグラウンドで削除された後にトランザクションを実行しようとしている場合にも発生する可能性があります。これを避けるためにはcommitAllowingStateLoss()を使うべきです

編集3: 上記の解決策は、私が覚えているものから初期のsupport.v4ライブラリの問題を修正していました。それでも問題が解決しない場合 しなければならない また、 @ AlexLockwood のブログを参照してください。 フラグメントトランザクションとアクティビティ状態の損失

ブログ投稿からのまとめ(ただし、それを読むことを強くお勧めします)。

  • 絶対に ハニカム前のcommit()およびハニカム後のonPause()の後のonStop()トランザクション
  • Activityライフサイクルメソッド内でトランザクションをコミットするときは注意してください。 つかいます onCreate()onResumeFragments()およびonPostResume()
  • 非同期コールバックメソッド内でトランザクションを実行しない
  • 最後の手段としてのみcommitAllowingStateLoss()を使う
444
Ovidiu Latcu

この問題の原因をAndroidのソースコードで調べると、FragmentManagerImplクラスのmStateSavedフラグ(Activityで使用可能なインスタンス)の値がtrueになります。 Activity#onSaveInstanceStateからの呼び出しでバックスタックが保存されると(saveAllState)、trueに設定されます。その後、ActivityThreadからの呼び出しは、FragmentManagerImpl#noteStateNotSaved()dispatch()から利用可能なresetメソッドを使ってこのフラグをリセットしません。

私の見ている方法では、あなたのアプリが何をしていて何を使っているかによって、利用可能な修正がいくつかあります。

良い方法

何よりも先に:私は Alex Lockwoodの記事 を宣伝します。それから私がこれまでにやったことから:

  1. 状態情報を保持する必要がないフラグメントおよびアクティビティの場合は、 commitAllowStateLoss を呼び出します。ドキュメンテーションからの抜粋:

    アクティビティの状態が保存された後にコミットを実行できるようにします。アクティビティを後でその状態から復元する必要があるとコミットが失われる可能性があるため、これは危険です。したがって、ユーザーのUI状態が予期せずに変更されても問題ない場合にのみ使用してください。フラグメントが読み取り専用の情報を表示している場合は、これを使用しても問題ないと思います。あるいは編集可能な情報を表示している場合でも、コールバックメソッドを使用して編集した情報を保持します。

  2. トランザクションがコミットされた直後( commit() を呼び出しただけ)、 FragmentManager.executePendingTransactions() を呼び出します。

お勧めしない方法:

  1. Ovidiu Latcuが上述したように、super.onSaveInstanceState()を呼び出さないでください。しかし、これはあなたがあなたの活動の全体の状態を断片の状態と共に失うことを意味します。

  2. onBackPressedをオーバーライドし、そこでfinish()だけを呼び出します。アプリケーションがFragments APIを使用していない場合は、これで問題ありません。 super.onBackPressedのようにFragmentManager#popBackStackImmediate()への呼び出しがあります。

  3. Fragments APIの両方を使用していてアクティビティの状態が重要で重要な場合は、リフレクションAPI FragmentManagerImpl#noteStateNotSaved()を使用して呼び出すことを試みることができます。しかし、これはハックです、またはそれは回避策であると言うことができます。嫌いですが、私の場合は、推奨されないコード(TabActivityおよびLocalActivityManager)を使用するレガシーアプリのコードを持っているので、それはまったく問題ありません。

以下はリフレクションを使用するコードです。

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    invokeFragmentManagerNoteStateNotSaved();
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeFragmentManagerNoteStateNotSaved() {
    /**
     * For post-Honeycomb devices
     */
    if (Build.VERSION.SDK_INT < 11) {
        return;
    }
    try {
        Class cls = getClass();
        do {
            cls = cls.getSuperclass();
        } while (!"Activity".equals(cls.getSimpleName()));
        Field fragmentMgrField = cls.getDeclaredField("mFragments");
        fragmentMgrField.setAccessible(true);

        Object fragmentMgr = fragmentMgrField.get(this);
        cls = fragmentMgr.getClass();

        Method noteStateNotSavedMethod = cls.getDeclaredMethod("noteStateNotSaved", new Class[] {});
        noteStateNotSavedMethod.invoke(fragmentMgr, new Object[] {});
        Log.d("DLOutState", "Successful call for noteStateNotSaved!!!");
    } catch (Exception ex) {
        Log.e("DLOutState", "Exception on worka FM.noteStateNotSaved", ex);
    }
}

乾杯!

73
gunar

フラグメントアクティビティのonSaveInstanceState()が呼び出された後にフラグメントトランジションを実行しようとすると、このような例外が発生します。

これが起こりうる理由の1つは、アクティビティが停止したときにAsyncTask(またはThread)を実行したままにしておくことです。

onSaveInstanceState()が呼び出された後の遷移は、システムがリソースのアクティビティを再利用し、後でそれを再作成した場合に失われる可能性があります。

34
FunkTheMonk

フラグメントを表示する前にsuper.onPostResume()を呼び出すか、super.onPostResume()を呼び出した後にonPostResume()メソッドでコードを移動するだけです。これで問題は解決します。

27
MJ.Ahmadi

これは、画面がロックされて\空白になり、Activity +ダイアログのインスタンス状態が保存された後にダイアログフラグメントでdismiss()を呼び出すときにも発生する可能性があります。この呼び出しを回避するには

dismissAllowingStateLoss()

文字通り毎回、ダイアログを閉じるたびに、その状態を気にする必要はなくなります。そのため、これで問題ありません。実際には状態を失うことはありません。

18
Brian Dilley

短くて実用的な解決策:

簡単な手順に従ってください。

ステップ1:それぞれのフラグメントのonSaveInstanceState状態をオーバーライドします。そしてそれからスーパーメソッドを削除します。

@Override
public void onSaveInstanceState(Bundle outState) {
};

ステップ2:CommitAllowingStateLoss()を使用してください。 commit()の代わりに。フラグメント操作中。

fragmentTransaction.commitAllowingStateLoss();
17
Basbous

私はライフサイクルの状態はあなたが次のチェックを持つことができるAndroidサポートlib v26.1.0から始まるそのようなクラッシュを防ぐのを助けることができると思います:

if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){
  // Do fragment's transaction commit
}

またはあなたが試すことができます:

Fragment.isStateSaved()

詳細はこちら https://developer.Android.com/reference/Android/support/v4/app/Fragment.html#isStateSaved()

10
Jamal

これは私のために働いた...私自身でこれを見つけた...それがあなたを助けることを願っています!

1)グローバルな "静的" FragmentManager/FragmentTransactionを持っていません。

2)onCreate、常にFragmentManagerを再度初期化します。

以下のサンプル: -

public abstract class FragmentController extends AnotherActivity{
protected FragmentManager fragmentManager;
protected FragmentTransaction fragmentTransaction;
protected Bundle mSavedInstanceState;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedInstanceState = savedInstanceState;
    setDefaultFragments();
}

protected void setDefaultFragments() {
    fragmentManager = getSupportFragmentManager();
    //check if on orientation change.. do not re-add fragments!
    if(mSavedInstanceState == null) {
        //instantiate the fragment manager

        fragmentTransaction = fragmentManager.beginTransaction();

        //the navigation fragments
        NavigationFragment navFrag = new NavigationFragment();
        ToolbarFragment toolFrag = new ToolbarFragment();

        fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag");
        fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag");
        fragmentTransaction.commitAllowingStateLoss();

        //add own fragment to the nav (abstract method)
        setOwnFragment();
    }
}
7
kurayami88

OnActivityForResult()メソッドでフラグメントを表示しようとしたときに常にこの問題が発生していたので、問題は次のとおりです。

  1. 私のアクティビティは一時停止され、停止されます。つまり、onSaveInstanceState()は(Honeycomb以前のデバイスとHoneycomb以前のデバイスの両方に対して)既に呼び出されています。
  2. 何らかの結果が発生した場合、フラグメントを表示/非表示にするトランザクションを作成したため、このIllegalStateExceptionが発生します。

私が作ったのは次のとおりです。

  1. 欲しいアクションが実行されたかどうかを判断するための付加価値(たとえば、camereから写真を撮る - isPhotoTaken) - 必要なトランザクションの量によって、ブール値または整数値になります。
  2. オーバーライドされたonResumeFragments()メソッドで、自分の値をチェックし、フラグメントトランザクションを行った後に必要になりました。この場合、onResumeFragments()メソッドで状態が返されたため、onSaveInstanceStateの後にcommit()は実行されませんでした。
6
Array

私はonconfigurationchangedで問題を解決しました。秘訣は、Androidのアクティビティライフサイクルによると、明示的にインテント(カメラインテント、またはその他のインテント)を呼び出したときです。その場合、アクティビティは一時停止され、onsavedInstanceが呼び出されます。アクティビティがアクティブだったとき以外の別の位置にデバイスを回転させたとき。フラグメントコミットなどのフラグメント操作を実行すると、不正な状態例外が発生します。それについて不満がたくさんあります。これはAndroidのアクティビティライフサイクル管理と適切なメソッド呼び出しに関するものです。それを解決するために私はこれをしました:1 - あなたの活動のonsavedInstanceメソッドをオーバーライドし、現在の画面の向き(縦または横)を決定してから活動が一時停止する前にそれにあなたの画面の向きを設定します。そのようにして、あなたはそれが他のものによって回転された場合にあなたがあなたの活動のためにあなたがあなたの活動のためにスクリーン回転をロックすることをロックする。その後、onresumeメソッドのアクティビティをオーバーライドし、今度はオリエンテーションモードをsensorに設定して、保存されたメソッドが呼び出された後にもう1回onconfigurationを呼び出して回転を適切に処理するようにします。

あなたはそれに対処するためにあなたの活動にこのコードをコピー/貼り付けすることができます:

@Override
protected void onSaveInstanceState(Bundle outState) {       
    super.onSaveInstanceState(outState);

    Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show();
    int orientation =this.getDisplayOrientation();
    //Lock the screen orientation to the current display orientation : Landscape or Potrait
    this.setRequestedOrientation(orientation);
}

//A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device 
public int getDisplayOrientation() {
    Display getOrient = getWindowManager().getDefaultDisplay();

    int orientation = getOrient.getOrientation();

    // Sometimes you may get undefined orientation Value is 0
    // simple logic solves the problem compare the screen
    // X,Y Co-ordinates and determine the Orientation in such cases
    if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        Configuration config = getResources().getConfiguration();
        orientation = config.orientation;

        if (orientation == Configuration.ORIENTATION_UNDEFINED) {
        // if height and widht of screen are equal then
        // it is square orientation
            if (getOrient.getWidth() == getOrient.getHeight()) {
                orientation = Configuration.ORIENTATION_SQUARE;
            } else { //if widht is less than height than it is portrait
                if (getOrient.getWidth() < getOrient.getHeight()) {
                    orientation = Configuration.ORIENTATION_PORTRAIT;
                } else { // if it is not any of the above it will defineitly be landscape
                    orientation = Configuration.ORIENTATION_LANDSCAPE;
                }
            }
        }
    }
    return orientation; // return value 1 is portrait and 2 is Landscape Mode
}

@Override
public void onResume() {
    super.onResume();
    Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show();
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
} 
5
douggynix

私は私のアプリで同じ問題を抱えています。前のクラスでsuper.onBackPressed();を呼び出し、現在のクラスでそのフラグメントを使用してcommitAllowingStateLoss()を呼び出すだけで、この問題は解決しました。

4
Peter

私はこの問題を得ました。しかし、この問題はcommitとcommitAllowStateLossに関連していないと思います。

次のスタックトレースと例外メッセージは、commit()に関するものです。

Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1341)
at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1352)
at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:595)
at Android.support.v4.app.BackStackRecord.commit(BackStackRecord.Java:574)

しかし、この例外はonBackPressed()によって引き起こされました。

Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
at Android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)
at Android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)

それらはすべてcheckStateLoss()が原因でした。

private void checkStateLoss() {
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }

mStateSavedはonSaveInstanceStateの後に真になります。

この問題はめったに起こりません。私はこの問題に遭遇したことがありません。私は問題を再発することはできません。

私は見つけた 問題25517

次のような場合に発生した可能性があります。

  1. バックキーはonSaveInstanceStateの後、新しいアクティビティが開始される前に呼び出されます。

  2. コード内でonStop()を使用する

私は問題の根本が何であるかわからない。だから私は醜い方法を使った。

@Override
public void onBackPressed() {

    try{
        super.onBackPressed();
    }catch (IllegalStateException e){
        // can output some information here
        finish();
    }
}
4
oO_ox

その問題に対する私の解決策は

フラグメント追加メソッドでは:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ...
    guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap);
    guideMap = guideMapFragment.getMap();
    ...
}

@Override
public void onDestroyView() {
    SherlockFragmentActivity a = getSherlockActivity();
    if (a != null && guideMapFragment != null) {
        try {
            Log.i(LOGTAG, "Removing map fragment");
            a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit();
            guideMapFragment = null;
        } catch(IllegalStateException e) {
            Log.i(LOGTAG, "IllegalStateException on exit");
        }
    }
    super.onDestroyView();
}

悪いかもしれませんが、もっと良いものを見つけることができませんでした。

4
mc.dev

私は同じ問題を抱えていた、IllegalStateExceptionを取得したが、commit()への私のすべての呼び出しをcommitAllowingStateLoss()で置き換えても役に立ちませんでした。

原因はDialogFragment.show()の呼び出しでした。

それで囲む

try {
    dialog.show(transaction, "blah blah");
}
catch(IllegalStateException e) {
    return;
}

そしてそれはそれをしました。はい、ダイアログを表示することはできませんが、この場合は問題ありませんでした。

私が最初にFragmentManager.beginTransaction()を呼び出したがcommit()を呼び出さなかった唯一の場所で、「commit()」を探したときには見つかりませんでした。

面白いことに、ユーザーはアプリを離れることはありません。その代わり、殺人犯はAdMobのインタースティシャル広告が現れた。

onSaveInstanceは、新しい方向に関連付けられたリソースをロードできるようにユーザーが画面を回転させると呼び出されます。

このユーザーが画面を回転させた後に[戻る]ボタンを押すことが可能です(これは、このユーザーがアプリを使用しているときに自分の携帯電話が故障した可能性もあるためです)。

3
dols

http://chris-alexander.co.uk/on-engineering/dev/Android-fragments-within-fragments/ を読んでください

記事。 fragment.isResumed()チェックは、onSaveInstanceStateメソッドを使わないでonDestroyViewで私を助けます。

2
andep

これは、フラグメントをロードしようとしているときにアクティビティの状態がonPause()に変更されたときに発生します。たとえば、データを取得してアクティビティにロードしようとしたとき次の活動に移動しました。

これを解決するには2つの方法があります。

Transaction.commit()の代わりにtransaction.commitAllowingStateLoss()を使用してフラグメントをロードできますが、実行されたコミット操作が失われる可能性があります。

または

フラグメントをロードするときにアクティビティが再開状態にあり、一時停止状態にならないようにしてください。ブール値を作成し、アクティビティがonPause()状態にならないかどうかを確認します。

@Override
public void onResume() {
    super.onResume();
    mIsResumed = true;
}

@Override
public void onPause() {
    mIsResumed = false;
    super.onPause();
}

次にフラグメントのロード中にアクティビティが存在するかどうかを確認し、アクティビティがフォアグラウンドの場合にのみロードします。

if(mIsResumed){
 //load the fragment
}
2
sharath kumar

私と同じ問題、そしてすべての記事、ブログ、そしてstackoverflowを一日かけて分析した結果、私は簡単な解決策を見つけました。 savedInstanceStateをまったく使用しないでください。これが1行のコードの条件です。フラグメントコードについて:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    .....
2
Tobia Caneschi

ありがとう@gunar、しかし私はもっと良い方法があると思います。

Docによると:

 * If you are committing a single transaction that does not modify the
 * fragment back stack, strongly consider using
 * {@link FragmentTransaction#commitNow()} instead. This can help avoid
 * unwanted side effects when other code in your app has pending committed
 * transactions that expect different timing.
 *
 * @return Returns true if there were any pending transactions to be
 * executed.
 */
public abstract boolean executePendingTransactions();

そのため、commitNowを使用して以下を置き換えます。

fragmentTransaction.commit();
FragmentManager.executePendingTransactions()
0
JianxinLi

マップフラグメントアクティビティでインテントチューザをキャンセルするために戻るボタンを押したときに、この例外が発生していました。私はこれを解決しました(フラグメントを初期化してトランザクションをコミットしていた)onResume()のコードをonStart()に置き換えたところ、アプリは正常に動作しました。それが役に立てば幸い。

0
DCS

私はとても面白いことに気づいた。私は自分のアプリに電話のギャラリを開くオプションを持っています、そしてデバイスはどのアプリを使うべきかを尋ねます、そこで私はダイアログから離れた灰色の領域をクリックし、この問題を見ました。 onPause、onSaveInstanceStateからonResumeに戻ると、onCreateViewにアクセスすることはありません。私はonResumeで取引をしています。だから私がやってしまったのはonPauseで否定されているがtrueCreateViewで本当であるというフラグを設定することです。フラグがtrueの場合、onResumeはonCommit、それ以外の場合はcommitAllowingStateLossを実行します。私は続けて時間を無駄にすることができましたが、ライフサイクルをチェックしたいと思いました。私はsdkversion 23であるデバイスを持っています、そして私はこの問題を得ません、しかし私は21である別のものを持っています、そして私はそれを見ます。

0
Juan Mendez

1つのフラグメントでstartactivityを使用すると、この例外が発生します。

Startactivityforresultを使用するように変更すると、例外はなくなりました:)

だからそれを修正する簡単な方法はstartActivityForResult apiを使用することです:)

0
Question

私のユースケース:アクティビティがあることを知らせるために断片的にリスナーを使いました。コールバックメソッドで新しいフラグメントコミットを行いました。これは初回は完全にうまく機能します。しかし、方向を変えると、アクティビティは保存されたインスタンスの状態で再作成されます。その場合、フラグメントは再び作成されず、フラグメントは古い破棄されたアクティビティであるリスナーを持つことを意味します。いずれにせよ、コールバックメソッドはアクション時に起動されます。それは問題を引き起こす破壊された活動に行きます。解決策は、リスナーを現在のライブアクティビティに合わせてリセットすることです。これで問題は解決します。

0
Ganesh Kanna

ちょっと調べた後、この問題に対する解決策はあなたのフラグメントがonresumeでコミットすることです。

出典: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/

0
jai

私が発見したのは、別のアプリがダイアログタイプで、バックグラウンドアプリにタッチを送信できるようにしている場合、ほとんどすべてのバックグラウンドアプリがこのエラーでクラッシュすることです。インスタンスが保存または復元された場合は、トランザクションが実行されるたびに確認する必要があると思います。

0
chris

私の場合は、同じエラー例外で、 "onBackPressed()"をランナブルに入れます(あなたはどのビューを使うこともできます):

myView.post(new Runnable() {
                    @Override
                    public void run() {
                        onBackPressed()
                    }
                });

理由はわかりませんが、機能します。

0
Alecs

あなたはfragmentManager.popBackStackImmediate()を呼び出しているかもしれません。活動が一時停止したとき。活動は終了していませんが、前景ではなく一時停止しています。 popBackStackImmediate()の前に、アクティビティが一時停止しているかどうかを確認する必要があります。

0
Murat

これはAndroid 4.2とサポートライブラリのソースで修正されています。

原因(および回避策)の詳細については、Googleのバグレポートを参照してください。 http://code.google.com/p/Android/issues/detail?id=19917

サポートライブラリを使用しているなら、このバグについて心配する必要はありません(長い間)[*]。ただし、APIを直接使用していて(つまりサポートライブラリのFragmentManagerを使用していない)、Android 4.2より下のAPIをターゲットにしている場合は、回避策の1つを試す必要があります。

[*]これを書いている時点では、Android SDKマネージャはまだこのバグを示す古いバージョンを配布しています。

編集この回答に賛成投票した人が誰かが混乱しているのは明らかなので、ここで明確にします。

いくつかの異なる(しかし関連した)状況があり、この例外がをスローする原因になります。上記の私の答えは、質問で議論された特定のインスタンス、すなわちその後修正されたAndroidのバグに言及しています。別の理由でこの例外が発生しているのであれば、フラグメントの状態が保存された後ではいけないときにフラグメントを追加または削除しているからです。このような状況にあるのなら、おそらく " ネストされたフラグメント - IllegalStateException" onSaveInstanceStateの後にこのアクションを実行できません " "が役に立つでしょう。

0
Benjamin Dobell

まあ、成功せずにすべての上記の解決策を試した後(基本的に私はトランザクションを持っていないので)。

私の場合、AlertDialogsとProgressDialogをフラグメントとして使用していましたが、回転時にFragmentManagerを要求するとエラーが発生することがありました。

私はいくつかの同様の投稿を混在させるための回避策を見つけました:

その3ステップの解決策は、すべてあなたのFragmentActivity上で行われます(この場合、それはGenericActivityと呼ばれます)。

private static WeakReference<GenericActivity> activity = null; //To avoid bug for fragments: Step 1 of 3

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    //To avoid bug for fragments: Step 2 of 3
    activity = new WeakReference<GenericActivity>(this);
}

@Override
public FragmentManager getSupportFragmentManager(){
    //To avoid bug for fragments: Step 3 of 3
    if (this == activity.get()) {
        return super.getSupportFragmentManager();
    }
    return activity.get().getSupportFragmentManager();
}
0
Antilope