1

我有一个屏幕,我想在单击某些视图时通过隐藏和显示(而不是替换它们)来交换两个片段。这是我的代码:

...
private Fragment currentFragment;
...
private void swapFragment(Fragment fragment) {
    FragmentTransaction ft = getChildFragmentManager().beginTransaction();

    if (currentFragment != null && !currentFragment.isHidden()) {
        ft.hide(currentFragment);
    }

    if (!fragment.isAdded()) {
        ft.add(R.id.fragment_holder, fragment);
    } else {
        ft.show(fragment);
    }
    ft.commit();

    currentFragment = fragment;
}
...

R.id.fragment_holder是一个框架布局。我没有<fragment>在我的布局中声明任何标签。本来我的swap方法就是这样...

getChildFragmentManager().beginTransaction().replace(R.id.fragment_holder, fragment).commit();

...但是由于我不会进入这里的原因,我想做显示/隐藏而不是替换。

从逻辑上讲,这应该非常简单:如果有片段显示,请先将其隐藏。如果是第一次显示这个片段,添加它,否则显示它。然后保存当前片段。

问题出在第一次启动时,这会崩溃,IllegalStateException并说明已添加片段。

11-12 08:36:49.098: E/AndroidRuntime(27293): FATAL EXCEPTION: main
11-12 08:36:49.098: E/AndroidRuntime(27293): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.my.package/com.my.package.activities.MainActivity}: java.lang.IllegalStateException: Fragment already added: ContactFragment{42263030 #0 id=0x7f0a006d}
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2324)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2374)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread.access$600(ActivityThread.java:154)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1248)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.os.Looper.loop(Looper.java:137)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread.main(ActivityThread.java:5242)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at java.lang.reflect.Method.invokeNative(Native Method)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at java.lang.reflect.Method.invoke(Method.java:511)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at dalvik.system.NativeStart.main(Native Method)
11-12 08:36:49.098: E/AndroidRuntime(27293): Caused by: java.lang.IllegalStateException: Fragment already added: ContactFragment{42263030 #0 id=0x7f0a006d}
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1175)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:616)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.Fragment.performStart(Fragment.java:1499)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:957)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:1882)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:573)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at com.my.package.activities.MainActivity.onStart(MainActivity.java:252)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1164)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.Activity.performStart(Activity.java:5233)
11-12 08:36:49.098: E/AndroidRuntime(27293):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2287)
11-12 08:36:49.098: E/AndroidRuntime(27293):    ... 11 more
4

1 回答 1

2

所以事实证明我的交换逻辑工作得很好。问题实际上是RadioGroup它可以被调用两次以在其子sOnCheckChangedListener之间进行一次检查更改。RadioButton这会产生两个FragmentTransactions,其中第二个会导致 IllegalStateException,因为它试图添加一个已经添加的片段。

我的解决方案是添加

if (fragment == currentFragment) return;

开始时swapFragment()

于 2013-11-12T17:47:24.533 回答