«Échec de la livraison» – onActivityForResult

J’ai un LoginActivity (User Logs in). C’est essentiellement sa propre Activity qui a pour thème une boîte de dialog (pour apparaître comme un dialog). Il apparaît sur un SherlockFragmentActivity . Ce que je veux, c’est: S’il y a une connexion réussie, il doit y avoir deux FragmentTransaction pour mettre à jour la vue. Voici le code:

Dans LoginActivity , si connexion réussie,

 setResult(1, new Intent()); 

Dans SherlockFragmentActivity :

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 1) { LoggedStatus = PrefActivity.getUserLoggedInStatus(this); FragmentTransaction t = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction(); SherlockListFragment mFrag = new MasterFragment(); t.replace(R.id.menu_frame, mFrag); t.commit(); // Set up Main Screen FragmentTransaction t2 = MainFragmentActivity.this.getSupportFragmentManager().beginTransaction(); SherlockListFragment mainFrag = new FeaturedFragment(); t2.replace(R.id.main_frag, mainFrag); t2.commit(); } } 

Il se bloque lors de la première validation, avec ce LogCat:

 E/AndroidRuntime(32072): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState E/AndroidRuntime(32072): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299) E/AndroidRuntime(32072): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310) E/AndroidRuntime(32072): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541) E/AndroidRuntime(32072): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525) E/AndroidRuntime(32072): at com.kickinglettuce.rate_this.MainFragmentActivity.onActivityResult(MainFragmentActivity.java:243) E/AndroidRuntime(32072): at android.app.Activity.dispatchActivityResult(Activity.java:5293) E/AndroidRuntime(32072): at android.app.ActivityThread.deliverResults(ActivityThread.java:3315) 

Tout d’abord, vous devriez lire mon article sur le blog pour plus d’informations (il explique pourquoi cette exception se produit et ce que vous pouvez faire pour la prévenir).

Appeler commitAllowingStateLoss() est plus un hack qu’un correctif. La perte d’État est mauvaise et doit être évitée à tout prix. Au moment où onActivityResult() est appelé, l’état de l’activité / du fragment n’a peut-être pas encore été restauré et, par conséquent, toutes les transactions effectuées pendant ce temps seront perdues. C’est un bug très important qui doit être corrigé! (Notez que le bogue ne se produit que lorsque votre Activity revient après avoir été tué par le système … ce qui, en fonction de la quantité de mémoire de l’appareil, peut parfois être rare). est très facile à attraper en testant).

Essayez plutôt de déplacer vos transactions dans onPostResume() (notez que onPostResume() est toujours appelé après onResume() et onResume() est toujours appelé après onActivityResult() ):

 private boolean mReturningWithResult = false; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mReturningWithResult = true; } @Override protected void onPostResume() { super.onPostResume(); if (mReturningWithResult) { // Commit your transactions here. } // Reset the boolean flag back to false for next time. mReturningWithResult = false; } 

Cela peut sembler un peu bizarre, mais ce genre de chose est nécessaire pour s’assurer que vos FragmentTransaction sont toujours validées après que l’état de l’activité a été restauré dans son état d’origine ( onPostResume() est garanti pour être appelé après l’ Activity ‘ s état a été restauré).

Ceci est similaire à la réponse de @Alex Lockwood mais en utilisant un Runnable :

 private Runnable mOnActivityResultTask; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mOnActivityResultTask = new Runnable() { @Override public void run() { // Your code here } } } @Override protected void onPostResume() { super.onPostResume(); if (mOnActivityResultTask != null) { mOnActivityResultTask.run(); mOnActivityResultTask = null; } } 

Si vous utilisez Android 3.0 ou supérieur avec lambdas , utilisez ceci:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mOnActivityResultTask = () -> { // Your code here } } 

Dans mon cas, j’ai été confronté aux mêmes problèmes à cause de la suite

 public void onBackPressed() { super.onBackPressed(); setIntents(); } private void setIntents(){ Intent searchConstaints=new Intent(); searchConstaints.putExtra("min",20); searchConstaints.putExtra("max",80); setResult(101,searchConstaints); finish(); } 

Résolu en réorganisant la fonction Appels dans onBackPressed ()

 public void onBackPressed() { setIntents(); super.onBackPressed(); } 

Vous pouvez utiliser ft.commitAllowingStateLoss() pour résoudre ce problème.

Raison: votre méthode ft.commit() été onSaveInstanceState après onSaveInstanceState .

votre logcat dit clairement: “Vous ne pouvez pas effectuer cette action après onSaveInstanceState” – votre Activity est déjà morte à ce stade et n’a pas pu retourner de résultats.

juste bouge:

 Intent in = new Intent(); setResult(1, in); 

à l’endroit dans votre Activity où il est encore vivant, et tout ira bien. et n’oubliez pas de finish() votre Activity pour délivrer le résultat.