creaity
creaity

Reputation: 665

java.lang.IllegalStateException: Fragment already added

I have a Problem with a Android App compiled and running with target SDK 4.3. The App has two Activities, a MainActivity which is also the Launcher Activity and a SecondActivity. Both are using Fragments. To Support older Devices also, the support lib is used.

In the following scenario it comes to the "IllegalStateException: Fragment already added" Error.

1) Start the app -> MainActivity is shown
2) switch to the SecondActivity with an Intent
3) Press the Home Button
4) Wait a longer time (tested with 24 hours)
5) press again the app icon -> Exception. If the time is shorter, the SecondActivity is shown like expected.

I have read a lot of the IllegalStateExceptions during Fragment handling, but all all of them pointed to a problem with a replace() method. In the Stacktrace, my own code is never called.

The Fragement is added in the Activies onCreate() Method:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(..);
    ListFragment listFragment = this.getCaptureListFragment();
    FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
    tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag");
    tx.commit(); 
}

private ListFragment getListFragment() {
    ListFragment listFragment = (ListFragment) this.getSupportFragmentManager().findFragmentByTag("list_fragment_tag");
    if (listFragment == null) {
        listFragment = new ListFragment();
    }
    return listFragment;
}


java.lang.RuntimeException: Unable to start activity    ComponentInfo{de.myexample.demo/de.myexample.demo.ui.SecondActivity}: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
    at android.app.ActivityThread.access$600(ActivityThread.java:141)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5103)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
    at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175)
    at android.support.v4.app.BackStackRecord.run(SourceFile:616)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460)
    at android.support.v4.app.FragmentActivity.onStart(SourceFile:556)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
    at android.app.Activity.performStart(Activity.java:5143)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
    ... 11 more
java.lang.IllegalStateException: Fragment already added: ListFragment{42283f58 #0 id=0x7f060094 de.myexample.demo.ui.ListFragment}
    at android.support.v4.app.FragmentManagerImpl.addFragment(SourceFile:1175)
    at android.support.v4.app.BackStackRecord.run(SourceFile:616)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1460)
    at android.support.v4.app.FragmentActivity.onStart(SourceFile:556)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
    at android.app.Activity.performStart(Activity.java:5143)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
    at android.app.ActivityThread.access$600(ActivityThread.java:141)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5103)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    at dalvik.system.NativeStart.main(Native Method)

Upvotes: 13

Views: 30853

Answers (4)

serefakyuz
serefakyuz

Reputation: 373

It is not necessary to create new boolean field for checking fragment's adding state. There is also a method in fragment. Just use it: myFragment.isAdded()

Upvotes: -3

Andy
Andy

Reputation: 7097

In order to reproduce this, one could activate "Don't keep activities" in Settings -> Developer options. Then pause and resume the activity.

That's so you don't have to wait 24 hours :)

Upvotes: 12

Jack Feng
Jack Feng

Reputation: 1675

The Fragment manager saves its state when exit. So you don't have to add your fragment again.

Do like this:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(..);

    if (savedInstanceState == null) {
        ListFragment listFragment = this.getCaptureListFragment();
        FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
        tx.add(R.id.MainFragmentContainer, listFragment, "list_fragment_tag");
        tx.commit(); 
    }
}

Upvotes: 0

creaity
creaity

Reputation: 665

Okay, solved in on my own.

I put all Fragments out in onPause() and store the state in some booleans. Depending on that booleans the Fragments are put in in onResume(). Than the launch is stable regardless how long the Activity was in the background.

boolean addList = false;

@Override
protected void onResume() {
    FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
    if (this.addList) {
        ListFragment list = this.getListFragment();
        tx.add(R.id.MainFragmentContainer, list, "list_fragment_tag");
    }

    tx.commit();
    super.onResume();

    this.addList = false;   

}

@Override
protected void onPause() {
    this.addList = this.getListFragment().isAdded();
    ...
    if (this.addList) {
        FragmentTransaction tx = this.getSupportFragmentManager().beginTransaction();
        tx.remove(this.getListFragment());
        tx.commit();
    }
    this.getSupportFragmentManager().executePendingTransactions();
    super.onPause();

}

Maybe that helps someone with the same problem

Upvotes: 17

Related Questions