web-dev-qa-db-fra.com

Fragment déjà ajouté à IllegalStateException

J'utilise cette méthode sur mon conteneur Activity pour afficher un BFrag

public void showBFrag()
{
    // Start a new FragmentTransaction
    FragmentTransaction fragmentTransaction = mFragmentMgr.beginTransaction();

    if(mBFrag.isAdded())
    {
        Log.d(LOG_TAG, "Show() BFrag");
        fragmentTransaction.show(mBFrag);   
    }
    else
    {
        Log.d(LOG_TAG, "Replacing AFrag -> BFrag");
        fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);
    }

    // Keep the transaction in the back stack so it will be reversed when backbutton is pressed
    fragmentTransaction.addToBackStack(null);

    // Commit transaction
    fragmentTransaction.commit();        
}

Je l’appelle de mon activité conteneur; pour la première fois: 

  • entre dans la déclaration else et mBFrag remplace mAFrag. 

Puis j'appuie sur le bouton retour:

  • et l'opération est inversée (mAFrag est affiché, mais est-ce que mBFrag est supprimé?). 

Ensuite, j'avance de nouveau en appelant showBFrag () à partir de la même activité: 

  • et il entre de nouveau dans la déclaration else. (je peux donc en déduire que mBFrag n'est pas ajouté)
  • mais j'ai un Fragment déjà ajouté à IllegalStateException ... (alors pourquoi ne pas entrer dans l'instruction if à la place?)

Alors:

  1. Pourquoi la méthode isAdded () ne renvoie-t-elle pas la valeur TRUE si je reçois déjà un Fragment déjà ajouté IllegalStateException ?? 
  2. L'opération popBackStack supprime-t-elle complètement les fragments ajoutés précédemment?
  3. Quel comportement ai-je mal compris? 

EDIT: Voici l’information complète de l’exception.

06-07 12:08:32.730: ERROR/AndroidRuntime(8576): Java.lang.IllegalStateException: Fragment already added: BFrag{40b28158 id=0x7f0c0085}
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at Android.app.BackStackRecord.doAddOp(BackStackRecord.Java:322)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at Android.app.BackStackRecord.replace(BackStackRecord.Java:360)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at Android.app.BackStackRecord.replace(BackStackRecord.Java:352)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at myPackageName.containerActivity.showBFrag() // This line: "fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);"
51
Axel M. Garcia

Enfin, ma solution consiste à exécuter remove () du fragment précédent et à ajouter () le nouveau. Bien que ce soit la méthode replace () que je devais faire ...

Mais je continue de deviner pourquoi la méthode replace () n'a pas bien fonctionné dans ce cas-là… c'est vraiment bizarre et je veux écarter le fait que c'est parce que je comprends mal ou que je fais quelque chose de mal.

41
Axel M. Garcia

Si l'état de l'activité a déjà été enregistré, l'appel n'est pas valide. Vous devez appeler commitAllowingStateLoss() à la place. J'espère que cela t'aides!

Edit: ok j’ai examiné de plus près votre problème, le problème est que vous essayez d’ajouter un fragment qui a déjà été ajouté. Même si vous utilisez remplacer ou supprimer des appels, vous ne pouvez pas le faire. Le seul moyen de contourner ce que j'ai trouvé est de créer une nouvelle instance d'un fragment et de l'ajouter à chaque fois. Une fois que vous avez supprimé ou remplacé un fragment, il est préférable de supprimer toutes vos références afin que le GC puisse s'en occuper.

12
schwiz

Probablement pas lié à ce problème directement, mais j'ai aussi remarqué que définir une transition sur FragmentTransaction provoquerait une exception IllegalStateException, alors que ne pas définir une transition ne le fera pas.

Voici le bogue pour ce problème: http://code.google.com/p/Android/issues/detail?id=25598

8
Johan Paul

Vérifiez si le frament est déjà ajouté ou non en utilisant la méthode fragment.isAdded () Ne remplacez ou ajoutez le fragment en conséquence

1
Jiju Induchoodan

J'ai utilisé ceci:

if (getFragmentManager().findFragmentByTag(newFragment.getClass().getName()) != null) {
   transaction.remove(newFragment);
 }

et ajouté fragment avec

MyFragment frag = new MyFragment(); 
transaction.add(R.id.container, frag, MyFragment.class.getName())

MyFragment.class.getName() signifie tag

1
Nartus Team

essayez ceci après fragmentTransection.replace ()

fragmentTransection.addToBackStack(null);
fragmentTransection.commitAllowingStateLoss();
1
Saleh Sheper

if (mFragment.isAdded ()) { revenir; // ou renvoie false/true, selon l'endroit d'où vous appelez }

0
Bombey77

Ce code fonctionne bien pour moi. essaye ça

((MiActivity)getActivity()).addAccount = new AddAccount();
((MiActivity)getActivity()).addAccount.setArguments(params);
fragmentManager = getActivity().getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container((MiActivity)getActivity()).addAccount);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
0
Muhammad Aamir Ali

Supprimer setOffscreenPageLimit de Viewpager a résolu mon problème . Merci.

0

Résolu en parcourant mes fragments et en vérifiant si isAdded () est vrai, puis en supprimant ce fragment. Plus de détails ici.

0
kylarsturn

J'ai essayé d'appeler FragmentTransaction.remove() à partir de onTabUnselected() et le problème a été résolu.

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    ft.add(R.id.fragment_container, fragment, null);
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    ft.remove(fragment);
}
0
ObviousChild