1

In my application I have one Activity, which consists of an overlaying side panel (navigation menu) and a LinearLayout, which is my main layout. I do transactions on my layout and replace fragments inside. I'm only allowing the user to navigate forward so I do not use a backstack at all. Instead, I use a Hashmap (a pseudo-cache) to keep the fragment instances in memory as the user navigates forward in the menu. The only problem with this approach is that I keep getting a crash when I try to replace the fragment that's currently in the main layout with a fragment from the cache (I ran it through the debugger and it says that the FragmentTransaction.replace() method check's the backstack(??)). I'm not quite sure what the issue is.

07-25 22:03:47.690: ERROR/AndroidRuntime(3141): FATAL EXCEPTION: main
07-25 22:03:47.690: ERROR/AndroidRuntime(3141): java.lang.IllegalStateException: Fragment already added: GuideFragment{409f2fd8 id=0x7f06008c}
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.app.BackStackRecord.doAddOp(BackStackRecord.java:322)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.app.BackStackRecord.replace(BackStackRecord.java:360)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.app.BackStackRecord.replace(BackStackRecord.java:352)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at StartActivity.changeContent(StartActivity.java:194)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at StartActivity$5.onClick(StartActivity.java:165)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.view.View.performClick(View.java:3117)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.view.View$PerformClick.run(View.java:11935)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.os.Handler.handleCallback(Handler.java:587)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.os.Looper.loop(Looper.java:132)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at android.app.ActivityThread.main(ActivityThread.java:4025)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at java.lang.reflect.Method.invokeNative(Native Method)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at java.lang.reflect.Method.invoke(Method.java:491)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
07-25 22:03:47.690: ERROR/AndroidRuntime(3141):     at dalvik.system.NativeStart.main(Native Method)
theisenp
  • 8,639
  • 5
  • 39
  • 47
Android Noob
  • 501
  • 1
  • 5
  • 5
  • Post the stacktrace from logcat – antlersoft Jul 25 '11 at 21:55
  • Updated. I guess the question I have is, is it possible to have Fragments be kept in a HashMap instead of a Backstack? According to the documentation, the Fragment gets destroyed if it doesn't get added to the Backstack. Yet, when I add it to the HashMap and retrieve it later, it's not null. Also, why is LogCat telling me that the Fragment was already added when it was never put on the Backstack to begin with? – Android Noob Jul 25 '11 at 23:52
  • Are you testing on the Emulator or on a physical device? I deal with fragments in a similar way in my app, and it runs fine on a physical device, but crashes with this same error on the emulator. – theisenp Aug 08 '11 at 19:37

3 Answers3

1

It seems your fragment is not able to replace in the View. While Inflating you might be missing third parameter of LayoutInflater.inflate().

Check, it should be like

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.session_frag, container, false);  
            return view;
        }
Chris Knight
  • 24,333
  • 24
  • 88
  • 134
candy
  • 734
  • 1
  • 11
  • 22
1

I have been having a similar problem. As I mentioned in my comment, my app runs fine on physical devices, but crashes on the Emulator. I'm not positive why it's throwing this Fragment already added error, but I found a workaround.

Before trying to replace a fragment, I first remove it (which seems counterintuitive, but it seems to work for me) using a try-catch block.

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
try
{
    fragmentTransaction.remove(guideFragment);
}
catch(IllegalStateException e)
{
    e.printStackTrace();
}
fragmentTransaction.replace(R.id.container, guideFragment, GUIDE_FRAGMENT_TAG);
fragmentTransaction.commit();

It seems that the replace() method has some strange behaviors, that don't always work as you expect them to. Others have had to use workarounds as well.

Community
  • 1
  • 1
theisenp
  • 8,639
  • 5
  • 39
  • 47
0

Check if fragment added works before you replace.

Kimate Richards
  • 150
  • 1
  • 7