web-dev-qa-db-ja.com

「onSaveInstanceStateの後にこのアクションを実行できません」-アクティビティのonResumeメソッドからこの例外を取得するのはなぜですか?

私のアクティビティは、ACTION_IMAGE_CAPTUREインテントでカメラを呼び出します。カメラアクティビティが正常に返された場合、onActivityResultコールバックにフラグを設定し、フラグの値に基づいてonResumeでフラグメントを開始し、キャプチャされた画像にキャプションを追加します。これはうまくいくようです。

OnSaveInstanceStateが呼び出された後にフラグメントトランザクションをコミットしようとしていることを訴える「ワイルド」からスタックトレースを取得しました。しかし、私はonResumeメソッドでコミットをしています!なぜAndroidこれについて文句を言うのですか?)がありますAndroid:configChanges = "orientation | keyboardHidden | keyboard | screenSize"私のAndroidManifest.xmlで設定されているので、向きの変更がこれをトリガーすることはありません。

これは、4.0.4を実行しているSamsung Galaxy S3(SGH-i747)で発生しました。

スタックは次のとおりです。

Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1314)
    at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1325)
    at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
    at Android.support.v4.app.BackStackRecord.commit(BackStackRecord.Java:532)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.performFragmentTransition(AddPhotosActivity2.Java:278)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.switchToCaptionsFragment(AddPhotosActivity2.Java:438)
    at com.Familiar.Android.FamiliarAppV1.AddPhotosActivity2.onResume(AddPhotosActivity2.Java:167)
    at Android.app.Instrumentation.callActivityOnResume(Instrumentation.Java:1158)
    at Android.app.Activity.performResume(Activity.Java:4544)
    at Android.app.ActivityThread.performResumeActivity(ActivityThread.Java:2448)
    at Android.app.ActivityThread.handleResumeActivity(ActivityThread.Java:2486)
    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1187)
    at Android.os.Handler.dispatchMessage(Handler.Java:99)
    at Android.os.Looper.loop(Looper.Java:137)
    at Android.app.ActivityThread.main(ActivityThread.Java:4514)
    at Java.lang.reflect.Method.invokeNative(Native Method)
    at Java.lang.reflect.Method.invoke(Method.Java:511)
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:980)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:747)
    at dalvik.system.NativeStart.main(Native Method)

どんな助けや知恵も大歓迎です。

29
PacificSky

I 思考私は答えを知っています-v4互換性ライブラリのFragmentActivityを使用しているため、onResumeではなくonResumeFragmentsでフラグメントトランザクションを実行する必要があります。誰か確認できますか?

55
PacificSky

メソッドcommitAllowingStateLoss()を使用できます

ただし、Googleの Androidリファレンス でわかるように、アクティビティの状態が失われる可能性があることに注意してください。

Commit()と似ていますが、アクティビティの状態が保存された後にコミットを実行できます。これは、アクティビティを後でその状態から復元する必要がある場合にコミットが失われる可能性があるため危険です。したがって、これはUIの状態がユーザーで予期せず変更されても構わない場合にのみ使用してください。

私の経験から、それはaddToBackStackメソッドが時々動作しなくなる可能性があるため、フラグメントに手動で追加する必要があり、もちろん状態は保存されません(テキストボックスのテキスト拡張子)

13
Asaf Manassen

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

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();
    }
}
3
kurayami88

更新ここで説明と解決策を見つけたと思います: http://code.google.com/p/Android/issues/detail?id = 23096#c4 そこに投稿された空のフラグメントの回避策を実装しましたが、これまでIllegalStateExceptionが発生しませんでした。

このようなアクティビティに非表示状態フラグメントを追加します。

@Override
protected void onCreate(final Bundle args) {
    ...
    if (args == null) {
        final FragmentManager fm = this.getSupportFragmentManager();
        final FragmentTransaction ft = fm.beginTransaction();
        final Fragment emptyFragmentWithCallback = new EmptyFragmentWithCallbackOnResume();
        ft.add(emptyFragmentWithCallback, EmptyFragmentWithCallbackOnResume.TAG);
        ft.commit();
    }

上記のリンクから次のコードを取得します。

public class EmptyFragmentWithCallbackOnResume extends Fragment {
OnFragmentAttachedListener mListener = null;

@Override
public void onAttach(SupportActivity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentAttachedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnFragmentAttachedListener");
    }
}

@Override
public void onResume() {
    super.onResume();
    if (mListener != null) {
        mListener.OnFragmentAttached();
    }
}

public interface OnFragmentAttachedListener {
    public void OnFragmentAttached();
}
}

そして、非表示の状態フラグメントによって呼び出されるカスタムonFragmentAttachedメソッドにonResumeまたはonResumeFragmentsに直行するフラグメントトランザクションを呼び出します。 onResumeFragmentsをまったく使用せず、onResumeでフラグメントトランザクションを発行しません。

要約すると、サポートライブラリとフラグメントを使用している場合は、onResumeを忘れ、onResumeFragmentsを忘れ、上記の回避策に基づいて独自の "onResume"を実装します。これはややばかげています。


確認できません。私はまったく同じ問題を抱えています。 onResumeFragmentsでフラグメントトランザクションを発行していますが。これは私がここに投稿したように動作していました: IllegalStateException-フラグメントサポートライブラリ .

エラーは4.0.3および4.0.4でのみ発生するようです。ただし、常に発生することも、エミュレーターで発生することもありません。

サポートライブラリrevを使用しています。 10およびAPI16。onResumeFragmentsでDialogFragment.showを呼び出し、ランダムユーザーからこのばかげた例外を継続的に取得します。ローカルで再現できません。

2
phlebas

OnActivityForResult()メソッドでフラグメントを表示しようとしたとき、私は常にこれを取得していました。そのため、問題は次のとおりでした。

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

私が作ったのは次です:

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

サポートv4ライブラリを使用して、ターゲットターゲティングAndroid 2.2(SDK 8))を最初に開発し、4.2(SDK 17)で使用を開始すると、フラグメントで同じ問題が発生しました。しかし、私のマニフェストをAndroid:minSdkVersion = "8" Android:targetSdkVersion = "17"に変更することで、私の問題は解決しました。

1
Andre Rocha

これをアクティビティに追加します。

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