web-dev-qa-db-fra.com

Comment le nouveau FragmentTransaction commitNow () fonctionne-t-il en interne?

La nouvelle méthode commitNow () ajoutée dans Android N et bibliothèque de support version 24 a une documentation limitée et un peu confuse.

Valide cette transaction de manière synchrone. Tous les fragments ajoutés seront initialisés et amenés complètement à l'état de cycle de vie de leur hôte et tous les fragments supprimés seront détruits en conséquence avant le retour de cet appel. La validation d'une transaction de cette manière permet d'ajouter des fragments en tant que composants encapsulés dédiés qui surveillent l'état du cycle de vie de leur hôte tout en offrant des garanties de commande plus fermes lorsque ces fragments sont entièrement initialisés et prêts. Les fragments qui gèrent des vues verront ces vues créées et attachées.

L'appel de commitNow est préférable à l'appel de commit () suivi de FragmentManager.executePendingTransactions () car ce dernier aura pour effet secondaire de tenter de valider toutes les transactions actuellement en attente, que ce soit le comportement souhaité ou non.

Les transactions validées de cette manière ne peuvent pas être ajoutées à la pile arrière du FragmentManager, car cela casserait les autres garanties de commande attendues pour les autres transactions validées de manière asynchrone. Cette méthode lèvera IllegalStateException si la transaction précédemment demandée pour être ajoutée à la pile arrière avec addToBackStack (String) .

Une transaction ne peut être validée qu'avec cette méthode avant que son activité de stockage ne sauvegarde son état. Si la validation est tentée après ce point, une exception sera levée. En effet, l'état après la validation peut être perdu si l'activité doit être restaurée à partir de son état. Voir commitAllowingStateLoss () pour les situations où il peut être correct de perdre la validation.

J'ai souligné en gras la partie que je trouve confuse.

Donc, mes principales préoccupations/questions sont:

1 - Ils NE PEUVENT PAS être ajoutés? Il indique que j'obtiendrai une exception IllegalStateException, sera-t-elle ou non ajoutée?

2 - J'accepte le fait que je ne peux pas l'utiliser si nous voulons ajouter un fragment dans le backstack. Ce que cela ne dit pas, c'est que vous obtenez cette exception:

Java.lang.IllegalStateException: This transaction is already being added to the back stack

!!!! ????

Donc, je ne peux pas appeler addToBackStack(String) moi-même parce qu'il l'appelle en interne pour moi? Je suis désolé mais ... quoi? Pourquoi? que faire si je ne veux pas qu'il soit ajouté dans le backstack? Et si j'essaie d'utiliser ce fragment du backstack plus tard, mais parce qu'il PEUT NE PAS être ajouté, plus tard, il n'est pas là?

Il semble que ce soit quelque chose de prévu si j'utilisais commitAllowingStateLoss(), mais je vois que commitNowAllowingStateLoss() existe aussi, alors ... quelle logique suit-il?

TL; DR

Comment commitNow () fonctionne-t-il en interne concernant le backstack?

53
Kaizie

C'est une bonne chose que Android Le code source est Open Source quand nous avons rencontré une question comme celle-ci!

Répondre

Jetons donc un œil à la source BackStackRecord ici

@Override
public void commitNow() {
    disallowAddToBackStack();
    mManager.execSingleAction(this, false);
}

@Override
public FragmentTransaction disallowAddToBackStack() {
    if (mAddToBackStack) {
        throw new IllegalStateException(
                "This transaction is already being added to the back stack");
    }
    mAllowAddToBackStack = false;
    return this;
}

Et mAddToBackStack sera défini sur true si vous appelez addToBackStack dans votre transaction.

Donc pour répondre à votre question, aucun addToBackStack n'est pas appelé en interne lorsque vous appelez commitNow(), c'est le message d'exception qui est ambigu. Je pense qu'il devrait dire You're not allowed to add to backstack when using commitNow() à la place du message actuel.

Prime:

Si nous approfondissons le code source de FragmentManager ici , commitNow() fait presque la même chose que executePendingTransactions() comme écrit ci-dessus, mais au lieu d'exécuter toutes les transactions précédemment validées, commitNow () ne validera que cette transaction.

Je pense que c'est la principale raison pour laquelle commitNow () n'autorise pas l'ajout au backstack car il ne peut garantir qu'il n'y a pas d'autre transaction en attente. Si commitNow () peut ajouter au backstack, il y a une possibilité que nous puissions casser notre séquence de backstack qui conduira à quelque chose d'inattendu.

77