30

我的活动使用 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)

感谢任何帮助或智慧。

4

7 回答 7

56

我知道答案 - 我正在使用来自 v4 兼容性库的 FragmentActivity,因此我需要在 onResumeFragments 而不是 onResume 中执行我的片段事务。有人可以确认吗?

于 2012-09-16T19:35:06.830 回答
15

您可以使用该方法 commitAllowingStateLoss()

但请注意,您可能会丢失活动状态,正如您在 google 的android 参考 中看到的那样,该参考通过以下方式解释了两者之间的不同

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

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

于 2013-06-15T16:56:43.997 回答
4

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

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();
    }
}
于 2013-04-19T09:18:08.460 回答
2

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

  1. 我的活动被暂停和停止,这意味着 onSaveInstanceState() 已经被调用(对于蜂窝前和蜂窝后设备)。
  2. 如果有任何结果,我会进行交易以显示/隐藏片段,这会导致此 IllegalStateException。

我做的是下一个:

  1. 用于确定我想要的操作是否已完成的附加值(例如,从camere 拍照-isPhotoTaken) - 它可以是布尔值或整数值,具体取决于您需要多少不同的事务。
  2. 在覆盖的 onResumeFragments() 方法中,我检查了我的值,并在进行了我需要的片段事务之后。在这种情况下,在 onSaveInstanceState 之后没有完成 commit(),因为在 onResumeFragments() 方法中返回了状态。
于 2014-09-06T12:09:38.633 回答
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 并不断从一些随机用户那里得到这个荒谬的异常。我无法在本地复制它。

于 2012-10-01T21:39:55.573 回答
1

我首先使用 support v4 库开发面向 android 2.2 (SDK 8) 的应用程序,当我开始使用 4.2 (SDK 17) 时,我的片段也遇到了同样的问题。但是将我的清单更改为 android:minSdkVersion="8" android:targetSdkVersion="17",解决了我的问题。也许这对你也有帮助。

于 2012-12-16T18:24:20.743 回答
0

将此添加到您的活动中:

 @Override
    protected void onSaveInstanceState(Bundle outState) {
        //No call for super(). Bug on API Level > 11.
    }
于 2019-01-30T06:48:47.927 回答