l'obtention de “l'exception IllegalStateException: vous ne Pouvez pas effectuer cette action après onSaveInstanceState”
J'ai un Live de l'application Android, et à partir de du marché, j'ai reçu à la suite de trace de la pile et je n'ai aucune idée de pourquoi sa se passe comme sa ne se passe pas dans le code de l'application, mais son être causée par un ou l'autre événement de l'application (hypothèse)
Je ne suis pas à l'aide de Fragments, il y a quand même une référence de FragmentManager.
Si un corps peut jeter quelque lumière sur certains faits cachés pour éviter ce type de problème:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
- Avez-vous trouvé une solution encore? Ayant le même problème ici: stackoverflow.com/questions/7575921/...
- Pas de chance dès maintenant 🙁
- J'ai eu le même problème et a trouvé une solution simple qui fonctionne pour moi
- Non vous n'avez pas. La vôtre préoccupations des boîtes de dialogue, et ce qui ne fonctionne pas. La ligne du haut de votre pile de trace de la correspondance n'est pas assez. Le reste est très différent. Je dis cela parce que je suis juste allé à la recherche à votre problème et c'est pas pour moi malheureusement.
- Utilisez-Vous un Thread ou AsynTask dans cette activité?
- Je discuter de cette erreur dans mon blog... vous devriez le lire. 🙂
- Si vous appuyez sur "Back" de votre peut @override (et mettre intention de nouvelle activité et de finition) recréer de l'activité avec tous les fragments. J'essaie maintenant et travaille
- stackoverflow.com/questions/39292191/..., Veuillez consulter le ce.
- vous obtenez l'accident, car une autre application est en avant et est dialogue type et permet de touches pour être envoyé à votre application.
Vous devez vous connecter pour publier un commentaire.
C'est le plus stupide bug que j'ai rencontré jusqu'à présent. J'ai eu un
Fragment
application fonctionne parfaitement pour API < 11, etForce Closing
sur API > 11.Je n'arrivais vraiment pas à comprendre ce qu'ils ont changé à l'intérieur de la
Activity
cycle de vie dans l'appel àsaveInstance
, mais j'voici comment j'ai résolu ce problème :Je n'arrive pas à faire l'appel à
.super()
et tout fonctionne très bien. J'espère que cela va vous faire économiser du temps.EDIT: après quelques recherches, c'est un bug dans le paquet de soutien.
Si vous avez besoin d'enregistrer l'instance, et d'ajouter quelque chose à votre
outState
Bundle
vous pouvez utiliser les éléments suivants :EDIT2: cela peut également se produire si vous essayez d'exécuter une transaction après votre
Activity
est allé en arrière-plan. Pour éviter cela, vous devez utilisercommitAllowingStateLoss()
EDIT3: Les solutions ci-dessus ont été truqués dans le soutien précoce.v4 bibliothèques de ce que je me souviens. Mais si vous avez toujours des problèmes avec cela, vous DOIT lire aussi @AlexLockwood 's blog : Fragment de Transactions & l'Activité de l'État de la Perte
Résumé de l'article du blog (mais je vous recommande fortement de le lire) :
commit()
transactions aprèsonPause()
sur la pré-Nid d'abeille, etonStop()
sur le post-Nid d'abeilleActivity
du cycle de vie des méthodes. UtilisationonCreate()
,onResumeFragments()
etonPostResume()
commitAllowingStateLoss()
seulement comme un dernier recoursoutState
n'est pas nulle? En raison d'une NullPointerException peut se produire si c'est le cas...?!onPostResume
au lieu decommitAllowingStateLoss
comme il semble plus approprié et de manière stable.FragmentActivity#onResumeFragments()
ouActivity#onPostResume()
mais quelle est votre solution sur les situations qui le classe étend Fragment ?À la recherche dans le code source Android sur les causes de cette question donne le drapeau mStateSaved dans
FragmentManagerImpl
classe (exemple disponible en Activité) a la valeur vrai. Elle est définie à true lorsque la pile de retour est enregistré (saveAllState) sur appel de laActivity#onSaveInstanceState
.Ensuite, les appels de ActivityThread ne pas réinitialiser ce drapeau en utilisant les méthodes de réinitialisation de
FragmentManagerImpl#noteStateNotSaved()
etdispatch()
.La façon dont je le vois, il ya quelques correctifs disponibles, en fonction de ce que votre application est en train de faire et à l'aide de:
Bonnes façons
Avant toute chose: je voudrais faire de la publicité Alex Lockwood article. Puis, à partir de ce que j'ai fait jusqu'à présent:
Pour des fragments et des activités qui n'ont pas besoin de garder tout état de renseignements, appelez commitAllowStateLoss. Prises à partir de la documentation:
Juste après la transaction est commit (vous juste appelé
commit()
), faire un appel àFragmentManager.executePendingTransactions()
.Pas recommandé façons:
Comme Ovidiu Latcu mentionné ci-dessus, n'appelez pas
super.onSaveInstanceState()
. Mais cela signifie que vous perdez tout état de votre activité avec des fragments de l'état.Remplacer
onBackPressed
et y appeler seulementfinish()
. Cela devrait être OK si vous demande de ne pas utiliser des Fragments de l'API; comme danssuper.onBackPressed
il y a un appel àFragmentManager#popBackStackImmediate()
.Si vous utilisez les deux Fragments de l'API et de l'état de votre activité est important/vitale, alors vous pouvez essayer d'appeler à l'aide de la réflexion de l'API
FragmentManagerImpl#noteStateNotSaved()
. Mais c'est un hack, ou on pourrait dire que c'est une solution de contournement. Je ne l'aime pas, mais dans mon cas c'est tout à fait acceptable puisque j'ai un code à partir d'un héritage application qui utilise obsolète code (TabActivity
et implicitementLocalActivityManager
).Ci-dessous est le code qui utilise la réflexion:
Cheers!
Une exception se produit si vous essayez d'effectuer un fragment de transition après votre fragment de l'activité
onSaveInstanceState()
est appelée.Une raison de ce qui peut arriver, c'est que si vous laissez un
AsyncTask
(ouThread
) en cours d'exécution lorsqu'une activité s'arrête.Toutes les transitions après
onSaveInstanceState()
est appelée pourrait potentiellement être perdus si le système récupère l'activité pour les ressources et les recrée plus tard.super.onSaveInstanceState()
.Appelez simplement super.onPostResume() avant de montrer votre fragment ou de déplacer votre code dans onPostResume() après l'appel de la méthode super.onPostResume(). Ce résoudre le problème!
Cela peut également se produire lors de l'appel de
dismiss()
sur un fragment de dialogue après l'écran est verrouillé\effacé et l'Activité + de la boîte de dialogue état de l'instance a été enregistré. Pour contourner cet appel:Littéralement à chaque fois que je suis licencier un dialogue je ne m'inquiète pas à ce sujet de l'état plus de toute façon, donc c'est ok pour le faire - vous n'êtes pas en train de perdre tout l'état.
Court Et Solution de travail :
Suivez Les Étapes Simples :
Étape 1 : Remplacer onSaveInstanceState de l'état dans le fragment. Et supprimer super méthode d'elle.
Étape 2 : Utilisation CommitAllowingStateLoss(); au lieu de commit(); while fragment opérations.
Je pense que le Cycle de vie de l'état peut aider à prévenir de telles crash de départ de soutien Android lib v26.1.0 vous pouvez avoir à cocher suivantes:
ou vous pouvez essayer:
plus d'informations ici
https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved()
cela a fonctionné pour moi... trouvé ceci sur mon propre... espérons qu'il vous aide!
1) n'aura PAS de mondial "statique" FragmentManager /FragmentTransaction.
2) onCreate, TOUJOURS initialiser le FragmentManager encore!
exemple ci-dessous :-
J'étais toujours présent quand j'ai essayé de montrer fragment dans onActivityForResult() la méthode, de sorte que le problème était le suivant:
Ce que j'ai fait est le suivant: la
J'ai résolu le problème avec onconfigurationchanged. Le truc, c'est que, selon android activité du cycle de vie, lorsque vous demandé explicitement une intention(caméra à l'intention, ou d'un autre); l'activité est en pause et onsavedInstance est appelé dans ce cas. Lors de la rotation de l'appareil à une position différente, autre que celle au cours de laquelle l'activité a été active; faire fragment opérations telles que le fragment de commettre des causes Illégale de l'état d'exception. Il y a beaucoup de plaintes à ce sujet. C'est quelque chose sur android activité du cycle de vie de gestion et de bonne les appels de méthode.
Pour le résoudre j'ai fait ceci:
1-Remplacer le onsavedInstance méthode de votre activité, et de déterminer l'actuelle orientation de l'écran(portrait ou paysage), puis réglez votre orientation de l'écran en avant votre activité est en pause. de cette façon, l'activité permet de verrouiller la rotation de l'écran de votre activité dans le cas où il a été tourné par un autre.
2-ensuite , remplacer méthode onresume de l'activité, et de définir votre orientation mode de capteur de sorte que, après onsaved méthode est appelée, elle va appeler une fois de plus onconfiguration à traiter avec la rotation correctement.
Vous pouvez copier/coller ce code dans votre activité de traiter avec elle:
J'ai eu le même problème, l'obtention d'exception IllegalStateException, mais le remplacement de tous mes appels au commit() avec commitAllowingStateLoss() n'a pas aidé.
Le coupable était un appel à DialogFragment.show().
Je l'entourent avec
et qu'il a fait. OK, je n'ai pas à afficher la boîte de dialogue, mais dans ce cas, c'était bon.
C'était le seul endroit dans mon application, où j'ai d'abord appelé FragmentManager.beginTransaction (), mais ne s'est jamais appelé commit() donc je n'ai pas trouvé lorsque j'ai regardé pour "commit()".
La chose drôle est, l'utilisateur ne quitte jamais l'application. Au lieu que le meurtrier était un AdMob annonce interstitielle qui se montre.
Ma solution à ce problème a été
Fragment d'ajouter des méthodes:
Est peut-être mauvais, mais ne pouvais pas trouver quelque chose de mieux.
J'ai eu ce problème.Mais je pense que ce problème n'est pas lié à l'engagement et à commitAllowStateLoss.
La suite de trace de la pile et le message d'exception est sur commit().
Mais cette exception a été causé par onBackPressed()
Ils ont tous été provoqués par checkStateLoss()
mStateSaved sera vrai après onSaveInstanceState.
Ce problème se produit rarement.Je n'ai jamais rencontré ce problème.Je ne peux pas la réapparition du problème.
J'ai trouvé question 25517
Il pourrait avoir eu lieu dans les circonstances suivantes
Touche retour est appelée après onSaveInstanceState, mais avant la nouvelle activité est commencé.
utilisation onStop() dans le code
Je ne suis pas sûr de ce que la racine du problème.
J'ai donc utilisé une vilaine façon.
J'ai eu le même problème dans mon Application. J'ai résolu ce problème il suffit d'appeler la
super.onBackPressed();
sur la classe précédente et de l'appel de lacommitAllowingStateLoss()
sur la classe actuelle avec ce fragment.commitAllowingStateLoss()
au lieu decommit()
onSaveInstance sera appelée si l'utilisateur fait pivoter l'écran de sorte qu'il peut charger des ressources associées à la nouvelle orientation.
Il est possible que cet utilisateur fait pivoter l'écran, puis en appuyant sur le bouton retour (parce que c'est aussi possible que cet utilisateur fouilla leur téléphone pendant l'utilisation de votre application)
Lire
http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/
article.
le fragment.isResumed() vérification de m'aide dans onDestroyView w/o à l'aide de la méthode onSaveInstanceState.
Même question de moi et après une journée longue analyse de tous les articles, les blogs et les stackoverflow j'ai trouvé une solution simple. N'utilisez pas de savedInstanceState à tous, c'est la condition avec une seule ligne de code. Sur le fragment de code:
Ce qui se passe chaque fois que vous essayez de charger un fragment, mais l'activité a changé son état d'onPause().Cela arrive par exemple lorsque vous essayez d'extraire les données et de le charger dans l'activité, mais au moment où l'utilisateur a cliqué sur quelques boutons et l'a déplacé à la prochaine activité.
Vous pouvez résoudre ce problème de deux façons
Vous pouvez utiliser la transaction.commitAllowingStateLoss() au lieu de transaction.commit() pour charger fragment, mais vous risquez de perdre opération de validation qui est fait.
ou
Assurez-vous que l'activité est à reprendre et ne pas aller à la pause lors du chargement d'un fragment.
Créer une valeur de type boolean et de vérifier si l'activité ne va pas onPause() de l'état.
puis pendant le chargement fragment de vérifier si l'activité est présente et ne charge que lorsque l'activité est au premier plan.
Bien, après avoir essayé toutes les solutions ci-dessus sans succès (parce que, fondamentalement, je n'ai pas de transactions).
Sur mon cas, j'ai été en utilisant AlertDialogs et ProgressDialog que des fragments qui, parfois, sur la rotation, lors de la demande de FragmentManager, l'erreur augmente.
J'ai trouvé une solution de contournement mélange de plusieurs des postes similaires:
Son une solution en 3 étapes, tout se fait sur votre FragmentActivity (dans ce cas, elle est appelée GenericActivity):
Lorsque j'utilise startactivity dans un fragment, je vais obtenir cette exception;
Quand j'ai changer pour utiliser le startactivityforresult, l'exception est parti 🙂
De sorte que le moyen facile de fixer c'est l'utilisation de la startActivityForResult api 🙂
Je recevais cette exception lorsque j'étais en appuyant sur bouton retour pour annuler l'intention sélecteur sur ma carte fragment de l'activité.
J'ai résolu ce problème en remplaçant le code de onResume()(où j'ai été initialisation du fragment et de commettre de transaction) à onStart() et que l'application fonctionne bien maintenant.
Espérons que cela aide.
C'est corrigé dans Android 4.2 et également dans la bibliothèque de prise en charge de la source.[*]
Pour les détails de la cause et des solutions de rechange) reportez-vous à la Google rapport de bug:
http://code.google.com/p/android/issues/detail?id=19917
Si vous utilisez la bibliothèque de prise en charge, alors vous ne devriez pas avoir à vous soucier de ce bug (pour longtemps)[*]. Toutefois, si vous utilisez l'API directement (c'est à dire Non à l'aide de la bibliothèque de prise en charge du FragmentManager) et le ciblage d'une API ci-dessous Android 4.2, alors vous aurez besoin d'essayer l'une des solutions de rechange.
[*] Au moment de la rédaction de l'Android SDK Manager est encore la distribution d'une ancienne version qui présente ce bug.
Modifier je vais ajouter quelques précisions ici parce que je n'ai évidemment quelque peu confus quiconque bas-voté cette réponse.
Il y a différentes (mais liées) de circonstances qui peuvent causer cette exception. Ma réponse ci-dessus se réfère à l'instance spécifique discuté de la question à savoir un bug sur Android qui a par la suite été corrigé. Si vous êtes l'obtention de cette exception pour une autre raison, c'est parce que vous êtes en train d'ajouter/enlever des fragments lorsque vous ne devriez pas être (après fragment états ont été enregistrées). Si vous êtes dans une telle situation, alors peut-être "Imbriquée Fragments - IllegalStateException “ne Peut pas effectuer cette action après onSaveInstanceState”" peut être utiliser pour vous.
Après des recherches un peu la solution à ce problème est de faire votre fragment s'engage dans la onresume.
Source: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/
Mon cas d'utilisation: j'ai utilisé de l'écouteur dans le fragment de notifier à l'activité que quelque chose s'est passé. J'ai fait de nouveau fragment de s'engager sur la méthode de rappel. Cela fonctionne parfaitement bien sur la première fois. Mais d'un changement d'orientation de l'activité est recréé avec enregistrés l'état de l'instance. Dans ce cas, le fragment n'est pas créé de nouveau implique que le fragment ont l'auditeur qui est l'ancien détruit activité. De toute façon le retour d'appel de la méthode va se déclencher sur l'action. Il va à détruit l'activité qui cause le problème. La solution est de réinitialiser le port d'écoute du fragment avec direct en cours d'activité. Ce résoudre le problème.
Ce que j'ai trouvé est que si une autre application est la boîte de dialogue type et permet de touches pour être envoyé à l'arrière-plan de l'app puis, presque à n'importe quel fond app crash avec cette erreur.
Je pense que nous avons besoin de vérifier à chaque fois qu'une transaction est effectuée si l'instance a été sauvegardé ou restauré.
Dans mon cas, avec le même message d'erreur d'exception, j'ai mis le "onBackPressed()" dans un exécutable (vous pouvez utiliser n'importe quel de votre point de vue):
Je ne comprends pas pourquoi, mais ça fonctionne!
Vous peut-être appeler fragmentManager.popBackStackImmediate(); lorsque l'activité est suspendue. L'activité n'est pas fini, mais est en pause et pas sur le premier plan. Vous devez vérifier si l'activité est en pause ou pas avant de popBackStackImmediate().
Merci @gunar, mais je pense qu'il y a une meilleure façon.
Selon doc :
Donc utiliser
commitNow
à remplacer:J'ai remarqué quelque chose de très intéressant. J'ai dans mon application la possibilité d'ouvrir le téléphone de la galerie et l'appareil vous demande ce que l'application à utiliser, là, j'ai cliquez sur la zone grise loin de la boîte de dialogue et vu ce problème. J'ai remarqué que mon activité va de onPause, onSaveInstanceState retour à onResume, il n'arrivera pas à visiter onCreateView. Je suis en train de faire des transactions à onResume. Donc ce que j'ai fini par le faire est de fixer un drapeau niés onPause, mais d'être vrai onCreateView. si le drapeau est vrai onResume puis faire onCommit, sinon commitAllowingStateLoss. Je pourrais continuer et perdre autant de temps mais je voulais vérifier le cycle de vie. J'ai un appareil qui est sdkversion 23, et je n'ai pas ce problème, mais j'en ai une autre qui est 21, et là je le vois.
vous pouvez utiliser FragmentActivity.onStart avant popBackStackImmediate
comme ceci:
http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html
Je pense que cet appel
FragmentActivity.onStateNotSaved()
avant ces opérations pourrait être la meilleure option en ce moment.