obtenir une exception “IllegalStateException: impossible d’effectuer cette action après onSaveInstanceState”

J’ai une application Live Android, et depuis le marché, j’ai reçu la trace suivante de la stack et je ne sais pas pourquoi cela se produit car il ne se produit pas dans le code de l’application, mais

Je n’utilise pas Fragments, mais il y a une référence à FragmentManager. Si un organisme peut éclairer 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) 

C’est le bug le plus stupide que j’ai rencontré jusqu’à présent. Une application Fragment fonctionnait parfaitement pour les API <11 et Force Closing sur les API> 11 .

Je n’ai pas vraiment saveInstance ce qu’ils ont changé dans le cycle de vie de l’ Activity dans l’appel à saveInstance , mais voici comment j’ai résolu ce problème:

 @Override protected void onSaveInstanceState(Bundle outState) { //No call for super(). Bug on API Level > 11. } 

Je ne fais tout simplement pas l’appel à .super() et tout fonctionne bien. J’espère que cela vous fera gagner du temps.

EDIT: après quelques recherches supplémentaires, il s’agit d’un bogue connu dans le package de support.

Si vous devez enregistrer l’instance et append quelque chose à votre ensemble outState vous pouvez utiliser les éléments suivants:

 @Override protected void onSaveInstanceState(Bundle outState) { outState.putSsortingng("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE"); super.onSaveInstanceState(outState); } 

EDIT2: cela peut également se produire si vous essayez d’effectuer une transaction après que votre Activity disparu en arrière-plan. Pour éviter cela, vous devez utiliser commitAllowingStateLoss()

EDIT3: Les solutions ci-dessus corrigeaient les problèmes rencontrés dans les premières bibliothèques support.v4. Mais si vous avez toujours des problèmes avec cela, vous devez également lire le blog de @AlexLockwood : Fragment Transactions & Activity State Loss

Résumé du billet de blog (mais je vous recommande fortement de le lire):

  • NE JAMAIS commit() transactions après onPause() sur pre-Honeycomb et onStop() sur post-Honeycomb
  • Faites attention lors de la validation des transactions dans les méthodes du cycle de vie des Activity . Utilisez onCreate() , onResumeFragments() et onPostResume()
  • Évitez d’effectuer des transactions dans les méthodes de rappel asynchrones
  • N’utilisez commitAllowingStateLoss() qu’en dernier recours

L’examen du code source d’Android sur les causes de ce problème indique que l’indicateur mStateSaved de la classe FragmentManagerImpl (instance disponible dans Activity) a la valeur true. Il est défini sur true lorsque la stack arrière est enregistrée (saveAllState) lors d’un appel à partir de l’ Activity#onSaveInstanceState . Par la suite, les appels de ActivityThread ne réinitialisent pas cet indicateur en utilisant les méthodes de réinitialisation disponibles de FragmentManagerImpl#noteStateNotSaved() et dispatch() .

La façon dont je le vois, il existe des correctifs disponibles, en fonction de ce que fait votre application et en utilisant:

Bonnes manières

Avant toute chose: je ferais de la publicité pour l’ article d’Alex Lockwood . Ensuite, d’après ce que j’ai fait jusqu’à présent:

  1. Pour les fragments et les activités qui ne nécessitent aucune information d’état, appelez commitAllowStateLoss . Tiré de la documentation:

    Permet l’exécution de la validation après la sauvegarde de l’état d’une activité. Ceci est dangereux car la validation peut être perdue si l’activité doit être restaurée ultérieurement. Par conséquent, elle ne doit être utilisée que dans les cas où l’état de l’interface utilisateur change de manière inattendue pour l’utilisateur. Je suppose que cela convient si le fragment affiche des informations en lecture seule. Ou même s’ils affichent des informations modifiables, utilisez les méthodes de rappel pour conserver les informations modifiées.

  2. Juste après la validation de la transaction (vous venez d’appeler commit() ), appelez FragmentManager.executePendingTransactions() .

Moyens non recommandés:

  1. Comme Ovidiu Latcu mentionné ci-dessus, n’appelez pas super.onSaveInstanceState() . Mais cela signifie que vous perdrez l’état de votre activité avec des fragments d’état.

  2. Remplacez onBackPressed et n’y appelez que finish() . Cela devrait être OK si votre application n’utilise pas l’API Fragments; Comme dans super.onBackPressed il y a un appel à FragmentManager#popBackStackImmediate() .

  3. Si vous utilisez à la fois l’API Fragments et l’état de votre activité est important / vital, vous pouvez essayer d’appeler à l’aide de l’API de reflection FragmentManagerImpl#noteStateNotSaved() . Mais c’est un hack, ou on pourrait dire que c’est une solution de contournement. Je n’aime pas ça, mais dans mon cas, c’est tout à fait acceptable puisque j’ai un code d’une application héritée qui utilise du code obsolète ( TabActivity et implicitement LocalActivityManager ).

Voici le code qui utilise la reflection:

 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); invokeFragmentManagerNoteStateNotSaved(); } @SuppressWarnings({ "rawtypes", "unchecked" }) private void invokeFragmentManagerNoteStateNotSaved() { /** * For post-Honeycomb devices */ if (Build.VERSION.SDK_INT < 11) { return; } try { Class cls = getClass(); do { cls = cls.getSuperclass(); } while (!"Activity".equals(cls.getSimpleName())); Field fragmentMgrField = cls.getDeclaredField("mFragments"); fragmentMgrField.setAccessible(true); Object fragmentMgr = fragmentMgrField.get(this); cls = fragmentMgr.getClass(); Method noteStateNotSavedMethod = cls.getDeclaredMethod("noteStateNotSaved", new Class[] {}); noteStateNotSavedMethod.invoke(fragmentMgr, new Object[] {}); Log.d("DLOutState", "Successful call for noteStateNotSaved!!!"); } catch (Exception ex) { Log.e("DLOutState", "Exception on worka FM.noteStateNotSaved", ex); } } 

À votre santé!

Une telle exception se produira si vous essayez d’effectuer une transition de fragment après l’ onSaveInstanceState() de onSaveInstanceState() votre activité de fragment.

L’une des raisons pour lesquelles cela peut se produire est que vous laissez une AsyncTask (ou un Thread ) s’exécuter lorsqu’une activité est arrêtée.

Toutes les transitions après l’ onSaveInstanceState() de onSaveInstanceState() peuvent potentiellement être perdues si le système récupère l’activité pour les ressources et la recrée ultérieurement.

Appelez simplement super.onPostResume () avant d’afficher votre fragment ou déplacez votre code dans la méthode onPostResume () après avoir appelé super.onPostResume (). Cela résout le problème!

Cela peut également se produire lorsque vous appelez dismiss() sur un fragment de dialog après le locking de l’écran \ blanked et que l’état de l’instance de la boîte de dialog Activity + a été enregistré. Pour contourner cet appel:

 dismissAllowingStateLoss() 

Littéralement, chaque fois que je rejette un dialog, je ne me soucie plus de son état de toute façon, alors c’est bon à faire – vous ne perdez en fait aucun état.

Solution courte et fonctionnelle:

Suivez les étapes simples:

Étape 1 : Remplacez l’état onSaveInstanceState dans le fragment respectif. Et enlevez-en la méthode super.

 @Override public void onSaveInstanceState(Bundle outState) { }; 

Étape 2 : utilisez CommitAllowingStateLoss (); au lieu de commit (); tout en fragmentant les opérations.

 fragmentTransaction.commitAllowingStateLoss(); 

Cela a fonctionné pour moi … j’ai trouvé ça tout seul … j’espère que ça vous aidera!

1) N’ayez PAS de FragmentManager / FragmentTransaction global “statique”.

2) onCreate, TOUJOURS initialiser le FragmentManager!

échantillon ci-dessous: –

 public abstract class FragmentController extends AnotherActivity{ protected FragmentManager fragmentManager; protected FragmentTransaction fragmentTransaction; protected Bundle mSavedInstanceState; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedInstanceState = savedInstanceState; setDefaultFragments(); } protected void setDefaultFragments() { fragmentManager = getSupportFragmentManager(); //check if on orientation change.. do not re-add fragments! if(mSavedInstanceState == null) { //instantiate the fragment manager fragmentTransaction = fragmentManager.beginTransaction(); //the navigation fragments NavigationFragment navFrag = new NavigationFragment(); ToolbarFragment toolFrag = new ToolbarFragment(); fragmentTransaction.add(R.id.NavLayout, navFrag, "NavFrag"); fragmentTransaction.add(R.id.ToolbarLayout, toolFrag, "ToolFrag"); fragmentTransaction.commitAllowingStateLoss(); //add own fragment to the nav (abstract method) setOwnFragment(); } } 

J’obtenais toujours cela lorsque j’ai essayé d’afficher fragment dans la méthode onActivityForResult (), le problème était donc le suivant:

  1. Mon activité est suspendue et arrêtée, ce qui signifie que onSaveInstanceState () a déjà été appelé (pour les périphériques pré-Honeycomb et post-Honeycomb).
  2. En cas de résultat, j’ai effectué une transaction pour afficher / masquer fragment, ce qui provoque cette exception IllegalStateException.

Ce que j’ai fait est le suivant:

  1. Valeur ajoutée pour déterminer si une action est souhaitée (par exemple, prendre une photo à partir de camere – isPhotoTaken) – cela peut être une valeur booléenne ou un nombre entier dépendant du nombre de transactions différentes dont vous avez besoin.
  2. Dans la méthode override onResumeFragments (), j’ai vérifié ma valeur et après, j’ai fait des transactions de fragments dont j’avais besoin. Dans ce cas, commit () n’a pas été effectué après onSaveInstanceState, car l’état était retourné dans la méthode onResumeFragments ().

J’ai résolu le problème avec la configuration changée. L’astuce est que selon le cycle de vie de l’activité Android, lorsque vous avez explicitement appelé une intention (intention de la caméra, ou toute autre); l’activité est suspendue et onsavedInstance est appelée dans ce cas. Lors de la rotation de l’appareil dans une autre position que celle pendant laquelle l’activité était active; La réalisation d’opérations fragmentées telles que la validation de fragment entraîne une exception d’état illégal. Il y a beaucoup de plaintes à ce sujet. C’est quelque chose à propos de la gestion du cycle de vie des activités Android et des appels de méthode appropriés. Pour résoudre ce problème, procédez comme suit: 1-Remplacez la méthode onsavedInstance de votre activité et déterminez l’orientation actuelle de l’écran (portrait ou paysage), puis définissez l’orientation de votre écran avant la mise en pause de votre activité. De cette façon, l’activité verrouille la rotation de l’écran pour votre activité au cas où celle-ci aurait été pivotée par un autre. Remplacez ensuite la méthode d’activité en cours et définissez votre mode d’orientation sur capteur pour appeler une nouvelle fois la configuration après traitement de la rotation.

Vous pouvez copier / coller ce code dans votre activité pour y faire face:

 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Toast.makeText(this, "Activity OnResume(): Lock Screen Orientation ", Toast.LENGTH_LONG).show(); int orientation =this.getDisplayOrientation(); //Lock the screen orientation to the current display orientation : Landscape or Potrait this.setRequestedOrientation(orientation); } //A method found in stackOverflow, don't remember the author, to determine the right screen orientation independently of the phone or tablet device public int getDisplayOrientation() { Display getOrient = getWindowManager().getDefaultDisplay(); int orientation = getOrient.getOrientation(); // Sometimes you may get undefined orientation Value is 0 // simple logic solves the problem compare the screen // X,Y Co-ordinates and determine the Orientation in such cases if (orientation == Configuration.ORIENTATION_UNDEFINED) { Configuration config = getResources().getConfiguration(); orientation = config.orientation; if (orientation == Configuration.ORIENTATION_UNDEFINED) { // if height and widht of screen are equal then // it is square orientation if (getOrient.getWidth() == getOrient.getHeight()) { orientation = Configuration.ORIENTATION_SQUARE; } else { //if widht is less than height than it is portrait if (getOrient.getWidth() < getOrient.getHeight()) { orientation = Configuration.ORIENTATION_PORTRAIT; } else { // if it is not any of the above it will defineitly be landscape orientation = Configuration.ORIENTATION_LANDSCAPE; } } } } return orientation; // return value 1 is portrait and 2 is Landscape Mode } @Override public void onResume() { super.onResume(); Toast.makeText(this, "Activity OnResume(): Unlock Screen Orientation ", Toast.LENGTH_LONG).show(); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } 

Je pense que l’état du cycle de vie peut aider à empêcher un tel crash à partir du support Android lib v26.1.0, vous pouvez avoir le contrôle suivant:

 if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)){ // Do fragment's transaction commit } 

ou vous pouvez essayer:

 Fragment.isStateSaved() 

plus d’informations ici https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved ()

J’ai eu le même problème, obtenir IllegalStateException, mais remplacer tous mes appels à commit () par commitAllowingStateLoss () n’a pas aidé.

Le coupable était un appel à DialogFragment.show ().

Je l’entoure

 try { dialog.show(transaction, "blah blah"); } catch(IllegalStateException e) { return; } 

et ça l’a fait. OK, je n’arrive pas à montrer le dialog, mais dans ce cas, ça allait.

C’était le seul endroit dans mon application où j’ai d’abord appelé FragmentManager.beginTransaction () mais je n’ai jamais appelé commit () donc je ne l’ai pas trouvé quand j’ai cherché “commit ()”.

Ce qui est amusant, c’est que l’utilisateur ne quitte jamais l’application. Au lieu de cela, le tueur était une annonce interstitielle AdMob apparaissant.

Ma solution à ce problème était

Dans les méthodes d’ajout de fragment:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ... guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap); guideMap = guideMapFragment.getMap(); ... } @Override public void onDestroyView() { SherlockFragmentActivity a = getSherlockActivity(); if (a != null && guideMapFragment != null) { try { Log.i(LOGTAG, "Removing map fragment"); a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit(); guideMapFragment = null; } catch(IllegalStateException e) { Log.i(LOGTAG, "IllegalStateException on exit"); } } super.onDestroyView(); } 

Peut être mauvais, mais n’a rien trouvé de mieux.

J’ai le même problème dans mon application. J’ai résolu ce problème en appelant simplement le super.onBackPressed(); sur la classe précédente et en appelant commitAllowingStateLoss() sur la classe en cours avec ce fragment.

onSaveInstance sera appelé si un utilisateur fait pivoter l’écran pour charger des ressources associées à la nouvelle orientation.

Il est possible que cet utilisateur ait fait pivoter l’écran en appuyant sur le bouton Retour (car il est également possible que cet utilisateur ait tapé son téléphone pendant que vous utilisiez votre application)

J’ai eu ce problème.Mais je pense que ce problème n’est pas lié à commit et commitAllowStateLoss.

Le message de trace et d’exception de stack suivant concerne commit ().

 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 

Mais cette exception a été causée par onBackPressed ()

 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source) at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source) at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source) 

Ils ont tous été causés par checkStateLoss ()

 private void checkStateLoss() { if (mStateSaved) { throw new IllegalStateException( "Can not perform this action after onSaveInstanceState"); } if (mNoTransactionsBecause != null) { throw new IllegalStateException( "Can not perform this action inside of " + mNoTransactionsBecause); } 

mStateSaved sera vrai après onSaveInstanceState.

Ce problème se produit rarement.Je n’ai jamais rencontré ce problème.Je ne peux pas reproduire le problème.

J’ai trouvé le numéro 25517

Il est possible que cela se soit produit dans les circonstances suivantes

  1. La touche Retour est appelée après onSaveInstanceState, mais avant le démarrage de la nouvelle activité.

  2. utiliser onStop () dans le code

Je ne suis pas sûr de la racine du problème. Donc j’ai utilisé un moyen laid.

 @Override public void onBackPressed() { try{ super.onBackPressed(); }catch (IllegalStateException e){ // can output some information here finish(); } } 

Lire http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/

article. La vérification fragment.isResumed () m’aide dans onDestroyView sans utiliser la méthode onSaveInstanceState.

Même problème avec moi et après une journée d’parsing de tous les articles, blog et stackoverflow, j’ai trouvé une solution simple. N’utilisez pas du tout savedInstanceState, c’est la condition avec une ligne de code. Sur le code de fragment:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(null); ..... 

Cela se produit à chaque fois que vous essayez de charger un fragment mais que l’activité a changé à onPause (), par exemple lorsque vous essayez d’extraire des données et de les charger dans l’activité, mais lorsque l’utilisateur a cliqué sur un bouton et a déplacé à l’activité suivante.

Vous pouvez résoudre ce problème de deux manières

Vous pouvez utiliser transaction.commitAllowingStateLoss () au lieu de transaction.commit () pour charger fragment, mais vous risquez de perdre l’opération de validation effectuée.

ou

Assurez-vous que l’activité est en reprise et ne pas mettre en pause l’état lors du chargement d’un fragment. Créez un booléen et vérifiez si l’activité ne va pas à l’état onPause ().

 @Override public void onResume() { super.onResume(); mIsResumed = true; } @Override public void onPause() { mIsResumed = false; super.onPause(); } 

puis, pendant le chargement du fragment, vérifiez si l’activité est présente et charge uniquement lorsque l’activité est en avant-plan.

 if(mIsResumed){ //load the fragment } 

Eh bien, après avoir essayé toutes les solutions ci-dessus sans succès (parce que fondamentalement je n’ai pas de transactions).

Dans mon cas, j’utilisais AlertDialogs et ProgressDialog sous forme de fragments qui, parfois, lors de la rotation, lors de la demande du FragmentManager, l’erreur augmentait.

J’ai trouvé une solution de contournement mélangeant de nombreux articles similaires:

C’est une solution en 3 étapes, tout est fait sur votre FragmentActivity (dans ce cas, il s’appelle GenericActivity):

 private static WeakReference activity = null; //To avoid bug for fragments: Step 1 of 3 @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); //To avoid bug for fragments: Step 2 of 3 activity = new WeakReference(this); } @Override public FragmentManager getSupportFragmentManager(){ //To avoid bug for fragments: Step 3 of 3 if (this == activity.get()) { return super.getSupportFragmentManager(); } return activity.get().getSupportFragmentManager(); } 

Lorsque j’utilise startactivity dans un fragment, j’obtiendrai cette exception;

Lorsque je change pour utiliser startactivityforresult, l’exception a disparu 🙂

Donc, le moyen le plus simple de résoudre ce problème est d’utiliser l’api startActivityForResult 🙂

J’obtenais cette exception lorsque j’appuyais sur le bouton pour annuler le sélecteur d’intention sur mon activité de fragment de carte. J’ai résolu cela en remplaçant le code de onResume () où j’étais en train d’initialiser le fragment et en validant la transaction) sur onStart () et l’application fonctionne correctement maintenant. J’espère que cela aide.

Ceci est corrigé dans Android 4.2 et aussi dans la source de la bibliothèque de support.

Pour plus d’informations sur la cause (et les solutions possibles), consultez le rapport de bogue Google: http://code.google.com/p/android/issues/detail?id=19917

Si vous utilisez la bibliothèque de support, vous ne devriez pas avoir à vous soucier de ce bogue (pour longtemps) [*]. Cependant, si vous utilisez l’API directement (c.-à-d. N’utilisez pas FragmentManager de la bibliothèque de support) et si vous ciblez une API sous Android 4.2, vous devrez essayer l’une des solutions.

[*] Au moment de la rédaction du présent document, Android SDK Manager dissortingbue toujours une ancienne version présentant ce bogue.

Edit Je vais append quelques précisions ici parce que, de toute évidence, j’ai confondu quiconque a voté contre cette réponse.

Il y a plusieurs circonstances différentes (mais liées) qui peuvent causer cette exception . Ma réponse ci-dessus fait référence à l’instance spécifique discutée dans la question, à savoir un bogue dans Android qui a été corrigé par la suite. Si vous obtenez cette exception pour une autre raison, c’est parce que vous ajoutez / supprimez des fragments alors que vous ne devriez pas le faire (après que les états des fragments ont été enregistrés). Si vous êtes dans une telle situation, alors peut-être ” Nested Fragments – IllegalStateException” Impossible d’effectuer cette action après onSaveInstanceState ” ” peut vous être utile.

Après avoir recherché un peu, la solution à ce problème est de faire la validation de votre fragment dans le onresume.

Source: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/

Mon cas d’utilisation: J’ai utilisé auditeur dans fragment pour notifier une activité. J’ai fait un nouveau commit sur la méthode callback. Cela fonctionne parfaitement bien la première fois. Mais lors du changement d’orientation, l’activité est recréée avec l’état d’instance enregistré. Dans ce cas, le fragment n’est pas créé à nouveau, ce qui implique que le fragment a l’auditeur qui est l’ancienne activité détruite. De toute façon, la méthode de rappel sera déclenchée lors de l’action. Il va à l’activité détruite qui cause le problème. La solution consiste à réinitialiser l’écouteur en fragment avec l’activité en cours. Cela résout le problème.

Ce que j’ai trouvé, c’est que si une autre application est de type boîte de dialog et permet d’envoyer des contacts à une application en arrière-plan, presque toutes les applications en arrière-plan planteront avec cette erreur. Je pense que nous devons vérifier chaque fois qu’une transaction est effectuée si l’instance a été enregistrée ou restaurée.

Dans mon cas, avec la même exception d’erreur, j’ai mis “onBackPressed ()” dans un exécutable (vous pouvez utiliser n’importe lequel de vos vues):

 myView.post(new Runnable() { @Override public void run() { onBackPressed() } }); 

Je ne comprends pas pourquoi, mais ça marche!

Vous appelez peut-être fragmentManager.popBackStackImmediate (); quand l’activité est en pause. L’activité n’est pas terminée mais est interrompue et non au premier plan. Vous devez vérifier si l’activité est suspendue ou non avant popBackStackImmediate ().

Merci @gunar, mais je pense qu’il y a une meilleure façon.

Selon doc:

  * If you are committing a single transaction that does not modify the * fragment back stack, strongly consider using * {@link FragmentTransaction#commitNow()} instead. This can help avoid * unwanted side effects when other code in your app has pending committed * transactions that expect different timing. * * @return Returns true if there were any pending transactions to be * executed. */ public abstract boolean executePendingTransactions(); 

Donc, utilisez commitNow pour remplacer:

 fragmentTransaction.commit(); FragmentManager.executePendingTransactions() 

J’ai remarqué quelque chose de très intéressant. J’ai dans mon application la possibilité d’ouvrir la galerie du téléphone et l’appareil demande quelle application utiliser, là je clique sur la zone grise de la boîte de dialog et j’ai vu ce problème. J’ai remarqué que mon activité va de onPause, onSaveInstanceState à onResume, il ne se trouve pas sur onCreateView. Je fais des transactions sur onResume. Donc, ce que j’ai fini par faire, c’est de mettre un drapeau en négation sur onPause, mais en étant vrai surCreateView. Si l’indicateur est vrai, onResume alors onCommit, sinon commetAllowingStateLoss. 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 un autre qui est le 21, et là je le vois.

vous pouvez utiliser FragmentActivity.onStart avant popBackStackImmediate

comme ça:

 public void backStackFragment() { this.start(); getFragmentManager().popBackStackImmediate(); } public void start(){ FragmentActivity a = getActivity(); if(a instanceof DepositPlanPadActivity){ ((DepositPlanPadActivity)a).onStart(); } if(a instanceof SmallChangePlanPad){ ((SmallChangePlanPad)a).onStart(); } if(a instanceof UserCenterActivity){ ((UserCenterActivity)a).onStart(); } } 

http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html