10

我有一个父片段活动,它有一个包含子 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();
}

现在,当应用程序首次启动时,这可以正常工作。

如果您转动设备以更改方向,则 Activity 会重新启动。所有片段都会在我使用时重新初始化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)

有谁知道为什么会这样?

谢谢

4

5 回答 5

11

当您旋转设备时,Android 会保存、销毁并重新创建您ActivityViewPager. Fragments由于ViewPager使用了FragmentManager您的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将在轮换时更新它们的回调引用。

于 2013-02-12T04:02:37.307 回答
0

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

    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((TestActivity)activity).contentFragment = this;
}
于 2013-02-11T22:14:18.643 回答
0

有类似的问题。基本上,如果 ViewPager 只有几个片段,则在当前活动中存储对它们的引用。不要调用 pagerAdapter 的 getItem(),因为它会创建一个新片段并且它没有附加到任何活动,这就是我们看到“活动已被破坏”异常的原因。如果不想保留片段引用,则可以使用 findViewWithTag() 方法获取片段对象。

于 2013-10-07T19:49:51.500 回答
0

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

@Override
protected void onPostResume() {
    super.onPostResume();
    // Commit your transactions here.
}
于 2014-08-20T14:04:55.833 回答
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();
}

只有当您调用二级(嵌套)片段时,您才应该传递一级片段的 parentActivity,因为在您将应用程序从前台带入后,这个错误似乎只存在于嵌套片段中。

于 2016-01-09T00:13:39.063 回答