IllegalStateException with Android Fragments

大城市里の小女人 提交于 2020-01-23 18:17:55

问题


I have a screen where I want to swap two fragments by hiding and showing (not replacing them) when certain views are clicked. Here is my code:

...
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 is a FrameLayout. I do not declare any <fragment> tags in my layout. Originally my swap method was simply this...

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

...but for reasons I won't get into here I want to do show/hide instead of replace.

Logically this should be pretty straightforward: if there's a fragment showing, hide it first. If it's the first time showing this fragment, add it, otherwise show it. Then save the current fragment.

The problem is on first launch, this crashed with an IllegalStateException stating the fragment has already been added.

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

回答1:


So it turns out my swapping logic works just fine. The problem is actually something with RadioGroup in which it's OnCheckChangedListener can be called twice for a single check change among its child RadioButtons. This produces two FragmentTransactions, the second of which causes the IllegalStateException because it tries to add an already added fragment.

The solution for me was to add

if (fragment == currentFragment) return;

at the beginning of swapFragment().



来源:https://stackoverflow.com/questions/19935400/illegalstateexception-with-android-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!