【问题标题】:IllegalStateException with Android Fragments带有 Android 片段的 IllegalStateException
【发布时间】:2013-11-12 17:04:20
【问题描述】:

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

...
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

【问题讨论】:

  • 你能告诉我们你的Activity类的onStart方法吗?
  • 您应该在添加新片段之前替换或删除片段。
  • @Homosapiens:那为什么会有显示和隐藏 API?
  • @Homosapiens:该链接确切地证实了我正在尝试做的事情。我想显示/隐藏而不是替换,以便以后可以在需要时再次显示它,而无需片段经历整个拆卸过程。

标签: android android-fragments fragmenttransaction


【解决方案1】:

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

我的解决方案是添加

if (fragment == currentFragment) return;

swapFragment()的开头。

【讨论】:

  • 您可能更喜欢if (fragment == null || fragment.equals(currentFragment))。根据内容而不是指针进行比较可能更有意义。
猜你喜欢
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多