FragmentManager:popBackStack()和IllegalStateException

时间:2016-02-08 15:48:52

标签: java android android-fragments

我有活动

public class MyActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener
{
    ...

    @Override
    public void onBackPressed()
    {
        if (getFragmentManager().getBackStackEntryCount() > 0) getFragmentManager().popBackStack();
    }
}

SimpleFragmentManager

private static void moveTo(BaseFragment fragment)
{
    if(fragment != null)
    {
        FragmentManager fragmentManager = _activity.getFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();

        //this  
        //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
        //or this   
        //ft.setCustomAnimations(R.animator.enter, R.animator.exit, R.animator.enter, R.animator.exit);
        //or this
        //ft.setCustomAnimations(R.animator.enter, R.animator.exit);

        BaseFragment currentFragment = getCurrentFragment();

        if(fragment != currentFragment)
        {
            ft.replace(_containerId, fragment, fragment.getType());
            if (currentFragment != null)
            {
                ft.addToBackStack(null);
            }
            ft.commit();
        }
    }
}

我的片段示例:

public class AFragment extends BaseFragment
{
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        if(view == null)
        {
            view = new ALayout(container.getContext());
            view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
        }

        return view;
    }
}

>>问题<<

测试是这样的,我在片段A 上,然后我打开片段B ,然后我立即改变动画片段的过程,我点击屏幕底部的后退按钮。

从第一次发生这种情况开始,但是多次执行这些步骤时,应用程序崩溃并出现错误:

  

E / AndroidRuntime:致命异常:主要                                                               过程:com.my.application,PID:2103                                                               java.lang.IllegalStateException:指定的子节点已经有了   家长。您必须首先在孩子的父母上调用removeView()。                                                                   在android.view.ViewGroup.addViewInner(ViewGroup.java:4309)                                                                   在android.view.ViewGroup.addView(ViewGroup.java:4145)                                                                   在android.view.ViewGroup.addView(ViewGroup.java:4086)                                                                   在android.view.ViewGroup.addView(ViewGroup.java:4059)                                                                   在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:985)                                                                   在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)                                                                   在android.app.BackStackRecord.run(BackStackRecord.java:793)                                                                   在android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535)                                                                   在android.app.FragmentManagerImpl $ 1.run(FragmentManager.java:482)                                                                   在android.os.Handler.handleCallback(Handler.java:739)                                                                   在android.os.Handler.dispatchMessage(Handler.java:95)                                                                   在android.os.Looper.loop(Looper.java:148)                                                                   在android.app.ActivityThread.main(ActivityThread.java:5417)                                                                   at java.lang.reflect.Method.invoke(Native Method)                                                                   在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)                                                                   在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

只有在使用过渡动画时才会出现此错误,此处为:

ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);

ft.setCustomAnimations(R.animator.enter, R.animator.exit, R.animator.enter, R.animator.exit);

ft.setCustomAnimations(R.animator.enter, R.animator.exit);

如果您不使用过渡动画,则没有错误!

我找到了很多这些主题,并且还发现了一个错误API:

1)https://code.google.com/p/android/issues/detail?id=77670

2)https://code.google.com/p/android/issues/detail?id=89244

我的SDK版本:

compileSdkVersion 23
buildToolsVersion '23.0.1'

重要的是,在片段中我没有删除查看这个:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
        ...
        ViewGroup parent = (ViewGroup) view.getParent();
        if(parent != null) parent.removeView(view);
}

因为我想使用单一视图

请告诉我,因为可以纠正这个错误吗?

>> P.S。解决方案的一个变体: 在有动画片段时禁用“后退”按钮。

1 个答案:

答案 0 :(得分:0)

我对API 28也有类似的问题。有时我想在创建片段后手动弹出堆栈。 popBackStack的直接调用给了我这个错误。这是我的解决方案(kotlin):

activity.supportFragmentManager.beginTransaction().runOnCommit {
    activity.supportFragmentManager.popBackStack()
}.commit()

这很丑陋,但是我没有找到更好的解决方案。您可以使用

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0)
        getFragmentManager().beginTransaction().runOnCommit(
            () -> getFragmentManager().popBackStack()
        ).commit();
}