“在onSaveInstanceState之后无法执行此操作” - 为什么我从我的activity的onResume方法中获取此异常?

时间:2012-09-16 19:31:10

标签: android android-fragments illegalstateexception

我的活动使用ACTION_IMAGE_CAPTURE意图调用相机。如果相机活动成功返回,我在onActivityResult回调中设置了一个标志,并根据标志的值我在onResume中启动一个片段,为捕获的图像添加标题。这似乎工作正常。

我刚从“狂野”中得到一个堆栈跟踪抱怨我在调用onSaveInstanceState后尝试提交片段事务。但我正在使用onResume方法进行提交!为什么android会抱怨这个?我的AndroidManifest.xml中设置了 android:configChanges =“orientation | keyboardHidden | keyboard | screenSize”,因此方向更改不应触发此....

这发生在运行4.0.4的三星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)

感谢任何帮助或智慧。

7 个答案:

答案 0 :(得分:55)

认为我知道答案 - 我正在使用v4兼容库中的FragmentActivity,所以我需要在onResumeFragments而不是onResume中执行我的片段事务。有人可以证实吗?

答案 1 :(得分:13)

您可以使用方法commitAllowingStateLoss()

但请注意,您可能会失去活动状态 正如你在谷歌android reference中看到的那样 用以下方式解释两者之间的差异

  

与commit()类似,但允许在保存活动状态后执行提交。这很危险,因为如果活动需要稍后从其状态恢复,则提交可能会丢失,因此这应仅用于UI状态可以在用户上意外更改的情况。

根据我的经验,它可能导致addToBackStack方法有时无法工作,因此您需要在片段上手动添加它 当然,状态不会被保存(文本框文本分机)

答案 2 :(得分:3)

这对我有用......我自己发现了......希望它对你有帮助!

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 :(得分:2)

更新我想我在这里找到了解释和解决方案:http://code.google.com/p/android/issues/detail?id=23096#c4 我实现了那里发布的Empty Fragment Workaround,到目前为止没有更多的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();
}
}

并调用直接进入onResume或onResumeFragments的片段事务到我的自定义 onFragmentAttached 方法,该方法由不可见状态片段调用。我根本不使用onResumeFragments,也不在onResume中发出任何片段事务。

所以,总结一下。如果您正在使用支持库和片段,几乎忘记onResume,忘记onResumeFragments并基于上述解决方法实现您自己的“onResume”。 这有点荒谬。


我无法确认。我有完全一样的问题。即使我在onResumeFragments中发出片段事务。 这曾经像我在这里发布的那样工作:IllegalStateException - Fragment support library

似乎错误仅发生在4.0.3和4.0.4上。但它并不总是发生在我的模拟器中。

我正在使用支持lib rev。 10和API 16。 我在onResumeFragments中调用DialogFragment.show并不断从一些随机用户那里得到这个荒谬的例外。我无法在本地重现它。

答案 4 :(得分:1)

我首先使用支持v4库开发针对android 2.2(SDK 8)的应用程序,当我开始使用4.2(SDK 17)时,我的片段也遇到了同样的麻烦。但是将我的Manifest改为android:minSdkVersion =“8”android:targetSdkVersion =“17”,解决了我的问题。也许这也让你感到高兴。

答案 5 :(得分:1)

当我试图在onActivityForResult()方法中显示片段时,我总是得到这个,所以接下来是问题:

  1. 我的活动暂停并停止,这意味着已经调用了onSaveInstanceState()(对于蜂窝前蜂窝和后蜂窝设备)。
  2. 如果有任何结果,我将事务显示/隐藏片段,这会导致此IllegalStateException。
  3. 我接下来做了什么:

    1. 确定我想要的操作是否已完成的附加值(例如从camere拍摄照片 - isPhotoTaken) - 它可以是布尔值或整数值,具体取决于您需要多少不同的交易。
    2. 在重写onResumeFragments()方法时,我检查了我的值,并在完成了我需要的片段事务之后。在这种情况下,在onSaveInstanceState之后没有执行commit(),因为onResumeFragments()方法返回了状态。

答案 6 :(得分:0)

将此添加到您的活动中:

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