'IllegalStateException:在活动重启后调用'getSupportFragmentManager()'时,活动已被销毁

时间:2013-02-10 17:02:37

标签: android android-fragments android-viewpager illegalstateexception

我有一个父片段活动,其中包含一个包含子ViewPager的ViewPager。子ViewPager包含每个页面的片段。我使用回调接口(例如

)在这些子页面片段和顶级父片段活动之间进行通信
public interface Callbacks {
    public void onItemSelected(Link link);
}

在父片段活动中,我会监听onItemSelected个事件,例如

@Override
public void onItemSelected(Link link) {
    Bundle argumentsFront = new Bundle();
    argumentsFront.putParcelable(FragmentComments.ARG_ITEM_ID, link);
    fragmentComments = new FragmentComments();
    fragmentComments.setArguments(argumentsFront);
    getSupportFragmentManager().beginTransaction().replace(R.id.post_container, fragmentComments).commitAllowingStateLoss();
}

现在,首次启动应用时,此功能正常。

如果您转动设备以更改方向,则活动将重新启动。当我使用setRetainInstance(true);时,所有片段都会重新初始化(我不会在子ViewPager的页面片段中调用setRetainInstance(true),因为它不受支持)。但是,如果我单击子ViewPager的片段中的列表项,我会得到以下异常:

FATAL EXCEPTION: main
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)

有谁知道为什么会这样?

由于

5 个答案:

答案 0 :(得分:11)

当您旋转设备时,Android会保存,销毁并重新创建Activity及其ViewPager Fragments。由于ViewPager使用FragmentManager的{​​{1}},因此会为您保存并重复使用Activity(并且不会创建新的Fragments,因此它们将保留旧参考到你的(现已销毁的)原始Activity,你得到IllegalStateException

在您的孩子Fragments中,尝试以下内容:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    Log.v(TAG, "onAttach");

    // Check if parent activity implements our callback interface
    if (activity != null) {
        try {
            mParentCallback = (Callbacks) activity;
        }
        catch (ClassCastException e) {
        }
    }
}

然后当选择发生时:

if(mParentCallback != null) {
    mParentCallback.onItemSelected(selectedLink);
}

由于onAttach作为Fragment生命周期的一部分被调用,因此您的Fragments将在轮换时更新其回调引用。

答案 1 :(得分:0)

我有一个类似的问题,我认为这是因为片段被保留并且保持对被破坏活动的引用,我的解决方案是保持对活动中片段的引用,例如Fragment myfragment = null。然后在MyFragment中使用以下代码:

    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((TestActivity)activity).contentFragment = this;
}

答案 2 :(得分:0)

有类似的问题。基本上,如果ViewPager只有几个片段,那么在当前活动中存储对它们的引用。不要调用pagerAdapter的getItem(),因为它创建了一个新的片段,它没有附加到任何活动,这就是为什么我们看到“Activity已被销毁”的例外。如果您不想保留片段引用,则可以使用findViewWithTag()方法获取Fragment对象。

答案 3 :(得分:0)

在OnPostResume回调中提交事务为我解决了这个问题。感谢以下博客 http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

@Override
protected void onPostResume() {
    super.onPostResume();
    // Commit your transactions here.
}

答案 4 :(得分:0)

我有嵌套片段的这个问题,没有一个stackoverflow解决方案适合我。看来,支持库存在一个错误,当被解散的片段仍然存储指向前一个活动的指针时(因此getFragmentManager()只返回null,因为它是在已经被破坏的活动上调用的),这就是你需要自己管理指针的原因。我最终得到了以下解决方案:1。在第一级片段中,我正在保存指向方法

中活动的指针
public void onAttach(Activity activity) {
        super.onAttach(activity);
        parentActivity = activity; // parentActivity is static variable
}

2。在处理片段的活动中,我最终得到了这段代码:

private void launchFragment(Fragment fragment, Activity parent) {
            FragmentTransaction transaction;
            if(parent == null)
                transaction = mFragmentManager.beginTransaction();
            else    // for nested child fragments, workaround for Android parent pointer bug
                transaction = parent.getFragmentManager().beginTransaction();
            transaction.replace(R.id.container, fragment);
            transaction.addToBackStack(null);
            transaction.commit();
}

只有在调用SECOND级别(嵌套)片段时,才应传递FIRST级别片段的parentActivity,因为在您从前台启动应用程序后,似乎此错误仅适用于嵌套的。