web-dev-qa-db-fra.com

commitAllowingStateLoss () dans les activités de fragment

mon application utilise des activités fragmentées, elle est en mode portrait uniquement et il n’ya aucun moyen de faire pivoter l’écran.

A l'origine, j'utilisais la méthode commit(), mais je prévois maintenant de les changer indifféremment en commitAllowingStateLoss() pour les activités de fragment.

Y a-t-il une raison pour ne pas le faire sans discernement sans réévaluer chaque cas individuel d'utilisation d'un fragment?

34
CQM

Si je comprends bien, vous voulez dire: n’y a-t-il aucune raison de NE PAS le faire sans discernement sans réévaluer chaque cas individuel où j’utilise un fragment?

La réponse est oui - vous ne devriez pas le faire sans réévaluer soigneusement chaque cas individuel d'utilisation d'un fragment. 

Bien entendu, en empêchant les redémarrages dus aux modifications de configuration (rotations d'écran), vous avez éliminé l'un des principaux problèmes: l'utilisateur peut faire pivoter l'écran APRÈS un appel de onSaveInstanceState mais AVANT le commitAllowingStateLoss. Dans ce cas, un fragment ou une partie de l'interface utilisateur peut être perdu. Pour une discussion informelle à ce sujet, voir ceci post .

Cependant, vous devez envisager d'autres situations avant de remplacer commit par commitAllowingStateLoss.

  1. En gros, toute mise à jour de l'interface utilisateur entre onSaveInstanceState et commitAllowingStateLoss: Android: IllegalStateException - Quand est-elle levée?

  2. Si vous avez des fragments sans tête qui mettent à jour l'interface utilisateur de votre activité, certaines de leurs mises à jour risquent d'être perdues (voir this article ).

  3. Android peut "tuer" un fragment car le téléphone/onglet manque de ressources (voir ceci answer ).

Bien sûr, si les rotations d'écran sont empêchées, il est possible que onSaveInstanceState ne soit pas appelé, auquel cas la fenêtre d'opportunité pour la perte d'une mise à jour est augmentée.

Si vous décidez d'utiliser commitAllowingStateLoss, vous pouvez alors prendre certaines mesures pour minimiser les risques: par exemple. envisagez de faire une commitexecutePendingTransactions lors du prochain redémarrage de l'activité parent (je sais que vous ne voulez pas le faire, mais quelqu'un d'autre pourrait lire _/this ).

Enfin (encore une fois au cas où quelqu'un lirait ceci - ceci n'est pas pertinent dans votre cas), il existe probablement des moyens plus sûrs de traiter une variable IllegalStateException que de passer de commit à commitAllowStateLoss. Par exemple, vous pouvez simplement vous en tenir à commit et gérer la IllegalStateException. Vous pouvez également avoir frappé un bug sous Android et trouver une solution de contournement.

48
IanB
public abstract int commit ()

Planifie un commit de cette transaction. Le commit ne se produit pas immédiatement; il sera programmé en tant que travail sur le thread principal à effectuer la prochaine fois que ce thread est prêt.

Une transaction ne peut être validée avec cette méthode que si son activité contenante est sauvegardée. Si la validation est tentée après ce moment, une exception sera levée. Cela est dû au fait que l'état après la validation peut être perdu si l'activité doit être restaurée à partir de son état. Voir commitAllowingStateLoss () pour connaître les situations dans lesquelles il peut être bon de perdre le commit.

public abstract int commitAllowingStateLoss ()

Ajouté dans l'API niveau 11

Identique à commit () mais permet l'exécution de la validation après l'enregistrement de l'état d'une activité. Cela est dangereux car la validation peut être perdue si l'activité doit être restaurée ultérieurement, elle ne doit donc être utilisée que dans les cas où l'état de l'interface utilisateur peut changer de manière inattendue pour l'utilisateur.

FragmentActivity limitations

Avant Honeycomb (3.0), l'état d'une activité était enregistré avant la pause. Les fragments représentent une quantité importante de nouveaux états et sont suffisamment dynamiques pour que l'on veuille souvent qu'ils changent entre pause et arrêt. Ces classes lève une exception si vous essayez de modifier l'état du fragment après son enregistrement afin d'éviter une perte accidentelle de l'état de l'interface utilisateur. Cependant, ceci est trop restrictif avant Honeycomb, où l’état est enregistré avant la pause. Pour remédier à cela, lors d'une exécution sur des plates-formes antérieures à Honeycomb, aucune exception ne sera levée si vous modifiez des fragments entre la sauvegarde d'état et l'activité arrêtée. Cela signifie que dans certains cas, si l'activité est restaurée à partir de son dernier état enregistré, il peut s'agir d'un instantané légèrement avant ce que l'utilisateur a vu.

Donc, si vous n'êtes pas préoccupé par la perte de l’État, je pense que votre décision est acceptable… j’espère que cela vous aidera dans votre décision.

5
Diogo Bento
try {
    transaction.commit();
} catch (IllegalStateException e) {
    transaction.commitAllowingStateLoss();
}
2

Une meilleure idée serait d'utiliser commit () dans les rappels OnPostResume plutôt que d'utiliser commitAllowingStateLoss () sans discernement. Suite à blogpost fournit une explication détaillée http://www.androiddesignpatterns.coms.com/13/08/fragment-transaction-commit-state-loss.html

@Override
protected void onPostResume() {
    super.onPostResume();
    // Commit your transactions here.
}
2
Varun Bhatia

Vous pouvez remplacer la méthode suivante comme celle-ci

@Override
public void supportFinishAfterTransition() {
    finish();
    super.supportFinishAfterTransition();
}

cela a fonctionné pour moi.

0
Juan A. C. Isla