web-dev-qa-db-fra.com

java.lang.IllegalStateException: fragment déjà ajouté

J'ai un problème avec une application Android compilée et exécutée avec le SDK cible 4.3. L'application a deux activités, une activité principale qui est également l'activité de lancement et une deuxième activité. Les deux utilisent des fragments. Pour prendre en charge les périphériques plus anciens, la bibliothèque de support est utilisée. 

Dans le scénario suivant, l'erreur "IllegalStateException: le fragment a déjà été ajouté". 

1) Démarrer l'application -> MainActivity est affiché
2) passer à la deuxième activité avec une intention
3) Appuyez sur le bouton Home
4) Attendre plus longtemps (testé avec 24 heures)
5) appuyez de nouveau sur l'icône de l'application -> Exception. Si le temps est plus court, la seconde activité est affichée comme prévu.

J'ai lu beaucoup d'exceptions IllegalStateExceptions lors de la gestion des fragments, mais toutes ont signalé un problème avec une méthode replace (). Dans le Stacktrace, mon propre code n'est jamais appelé.

Le fractionnement est ajouté à la méthode Activies onCreate ():

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)
11
creaity

Ok, résolu par moi-même.

Je mets tous les fragments dans onPause () et stocke l'état dans des booléens. En fonction de ces booléens, les fragments sont placés dans onResume (). Le lancement est stable quelle que soit la durée d'activité de l'arrière-plan. 

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();

}

Peut-être que cela aide quelqu'un avec le même problème

14
creaity

Afin de reproduire cela, vous pouvez activer "Ne pas conserver les activités" dans Paramètres -> Options du développeur. Puis faites une pause et reprenez l'activité.

C'est pour que vous n'attendiez pas 24 heures :)

9
Andy

Le gestionnaire de fragments enregistre son état lors de sa sortie. Donc, vous n'êtes pas obligé d'ajouter votre fragment à nouveau.

Fait comme ça:

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(); 
    }
}
0
Jack Feng