web-dev-qa-db-fra.com

Effacer la pile en utilisant des fragments

J'ai porté mon application Android en nid d'abeille et j'ai fait un grand refactor afin d'utiliser des fragments. Dans ma version précédente, lorsque j’appuyais sur le bouton Home, je faisais un ACTIVITY_CLEAR_TOP afin de réinitialiser la pile arrière. 

À présent, mon application est une simple activité comportant plusieurs fragments. Par conséquent, lorsque je clique sur le bouton Accueil, je remplace simplement l'un des fragments qu'il contient. Comment puis-je vider ma pile d'arrière-plan sans avoir à utiliser startActivity avec l'indicateur ACTIVITY_CLEAR_TOP

215
biquillo

J'ai posté quelque chose de similaire ici

De la réponse de Joachim, de Dianne Hackborn:

http://groups.google.com/group/Android-developers/browse_thread/thread/d2a5c203dad6ec42

J'ai fini par utiliser simplement:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
    fm.popBackStack();
}

Mais aurait également pu utiliser quelque chose comme:

FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

Ce qui fera apparaître tous les états jusqu'à celui qui est nommé. Vous pouvez alors simplement remplacer le fragment par ce que vous voulez

373
PJL

Répondre au commentaire de @ Warpzit et le rendre plus facile à trouver pour les autres.

Utilisation:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
132
Morten Holmgaard

La réponse acceptée ne m'a pas suffi. Je devais utiliser: 

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
17
belphegor

Fonctionne pour moi et moyen facile sans utiliser de boucle:

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
16
Md Mohsin

Effacer backstack sans boucles

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);

name est le paramètre addToBackStack ()

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)
13
georgehardcore

Je voulais juste ajouter: -

Sauter de pile en utilisant ce qui suit

fragmentManager.popBackStack ()

il s’agit simplement de supprimer les fragments de la transaction, aucun moyen de supprimer le fragment de l’écran ... donc idéalement, il se peut qu’il ne soit pas visible pour vous, mais il peut y avoir deux ou trois fragments empilés les uns sur les autres, et sur la touche arrière, l'interface utilisateur peut sembler encombrée, empilée.

Prenons juste un exemple simple: -

Supposons que vous avez un fragmentA qui charge Fragmnet B en utilisant fragmentmanager.replace () puis nous effectuons addToBackStack, pour enregistrer cette transaction . Le flux est donc: -

ÉTAPE 1 -> FragmentA-> FragmentB (nous sommes passés à FragmentB, mais le fragment A est en arrière-plan, pas visible).

Vous travaillez maintenant dans fragmentB et appuyez sur le bouton Enregistrer. Après l'enregistrement, vous devez revenir à fragmentA.

ETAPE 2-> Sur la sauvegarde de FragmentB, nous retournons à FragmentA.

ÉTAPE 3 -> L’erreur la plus courante serait… dans le fragment B, nous allons fragmenter Manager.replace () fragmentB avec fragmentA.

Mais ce qui se passe réellement, nous chargeons à nouveau le fragment A, en remplacement de FragmentB. Alors maintenant, il y a deux FragmentA (un de l’étape 1 et un de l’étape 3). 

Deux instances de FragmentsA sont empilées l'une sur l'autre, ce qui peut ne pas être visible, mais c'est là.

Donc, même si nous effaçons le backstack avec les méthodes ci-dessus, la transaction est effacée mais pas les fragments réels . Donc, idéalement, dans un tel cas particulier, il suffit de cliquer sur le bouton de sauvegarde pour revenir à fragmentA fm.popBackStack () ou fm.popBackImmediate () .

Donc, correct Step3-> fm.popBackStack () retourne à fragmentA, qui est déjà en mémoire.

8
Nicks

En lisant documentation et en étudiant le fragment id, il s’agit simplement de l’index de pile, ce qui fonctionne:

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Zero (0) est le bas de la pile. Le fait de l'afficher inclusivement efface la pile.

CAVEAT: Bien que cela fonctionne dans mon programme, j’ hésite un peu car la documentation de FragmentManager n’indique jamais que l’identifiant est l’index de pile. Il est logique que ce soit le cas, et tous mes journaux de débogage le prouvent, mais peut-être que dans certaines circonstances particulières, ce ne serait pas le cas? Quelqu'un peut-il confirmer cela d'une manière ou d'une autre? Si tel est le cas, la solution ci-dessus est la meilleure. Sinon, c'est l'alternative:

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
3
trans

Utilisez simplement cette méthode et transmettez les balises Context & Fragment jusqu'à ce que nous ayons besoin de supprimer les fragments de backstake.

Utilisation

clearFragmentByTag(context, FragmentName.class.getName());



public static void clearFragmentByTag(Context context, String tag) {
    try {
        FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();

        for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
            String backEntry = fm.getBackStackEntryAt(i).getName();
            if (backEntry.equals(tag)) {
                break;
            } else {
                 fm.popBackStack();
            }
        }
    } catch (Exception e) {
        System.out.print("!====Popbackstack error : " + e);
        e.printStackTrace();
    }
}
2
Arhat Baid

Cela fonctionne pour moi, essayez celui-ci:

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }
2
Alok Singh

Je travaille de cette façon:

public void showHome() {
    getHandler().post(new Runnable() {
        @Override
        public void run() {
            final FragmentManager fm = getSupportFragmentManager();
            while (fm.getBackStackEntryCount() > 0) {
                fm.popBackStackImmediate();
            }
        }
    });
}
1
saulobrito
private boolean removeFragFromBackStack() {
    try {
        FragmentManager manager = getSupportFragmentManager();
        List<Fragment> fragsList = manager.getFragments();
        if (fragsList.size() == 0) {
            return true;
        }
        manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
0
user3509903
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

L'appel à cette méthode serait très soigné.

  1. Aucune boucle requise.
  2. Si vous utilisez une animation par fragments, les animations ne seront pas trop nombreuses. Mais utiliser la boucle sera.
0
Wajid Ali

Salut ~ J'ai trouvé une solution beaucoup mieux, de: https://Gist.github.com/ikew0ng/8297033

    /**
 * Remove all entries from the backStack of this fragmentManager.
 *
 * @param fragmentManager the fragmentManager to clear.
 */
private void clearBackStack(FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() > 0) {
        FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
        fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
}
0
Chenxi