obtenir l'exception " IllegalStateException: ne peut pas effectuer cette action après onSaveInstanceState"

j'ai une application Android en direct, et du marché j'ai reçu la suite stack trace et je n'ai aucune idée pourquoi son happening comme son non happening dans le code d'application, mais son obtention causée par certains ou l'autre événement de l'application (hypothèse)

Je n'utilise pas de Fragments, il y a toujours 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)  
326
demandé sur dcool 2011-09-19 13:50:06

30 réponses

C'est le bogue le plus stupide que j'ai rencontré jusqu'à présent. J'avais une application Fragment qui fonctionnait parfaitement pour API < 11 , et Force Closing sur API > 11 .

Je ne pouvais vraiment pas comprendre ce qu'ils ont changé dans le cycle de vie Activity dans l'appel à saveInstance , mais je voici comment j'ai résolu cela:

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

Je ne fais pas 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 supplémentaires, c'est un" bug "connu dans le paquet de soutien.

si vous devez sauvegarder l'instance, et ajouter quelque chose à votre outState Bundle vous pouvez utiliser ce qui suit :

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

Edit 2: cela peut également se produire si vous tentez d'effectuer une transaction après que votre Activity est parti en arrière-plan. Pour éviter cela, vous devez utiliser commitAllowingStateLoss()

EDIT3: les solutions ci-dessus corrigeaient des problèmes dans le support initial.v4 libraries de ce dont je me souviens. Mais si vous avez encore des problèmes avec cela, vous doit aussi lire @AlexLockwood 's blog: fragments de Transactions & Perte D'État D'Activité

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

  • jamais commit() transactions après onPause() sur pre-Honeycomb, et onStop() sur post-Honeycomb
  • soyez prudent lorsque vous effectuez des transactions à l'intérieur des méthodes du cycle de vie Activity . Utilisation onCreate() , onResumeFragments() et onPostResume()
  • Evite d'effectuer des transactions à l'intérieur des méthodes de rappel asynchrones
  • utiliser commitAllowingStateLoss() en dernier recours seulement
436
répondu Ovidiu Latcu 2017-05-23 11:55:03

regarder dans le code source Android sur les causes de ce problème donne que le drapeau mStateSaved dans FragmentManagerImpl Classe (instance disponible en activité) a valeur vraie. Il est défini à true lorsque la pile arrière est sauvegardée (saveAllState) sur appel à partir de Activity#onSaveInstanceState . Ensuite, les appels D'ActivityThread ne réinitialisent pas ce drapeau en utilisant les méthodes de réinitialisation disponibles de FragmentManagerImpl#noteStateNotSaved() et dispatch() .

la façon dont je le vois Il ya quelques correctifs disponibles, en fonction de ce que votre application fait et utilise:

"1519190920 des" Bonnes manières

avant toute autre chose: je voudrais annoncer Alex Lockwood article . Puis, de ce que j'ai fait jusqu'à présent:

  1. pour les fragments et les activités qui n'ont pas besoin de conserver d'informations d'état, appelez commitAllowStateLoss . Extrait de la documentation:

    permet au commit d'être exécuté après la sauvegarde de l'état d'une activité. C'est dangereux parce que la propagation peut être perdue si l'activité doit être restaurée plus tard de son état, de sorte qu'elle ne devrait être utilisée que dans les cas où L'état de L'UI peut changer de façon inattendue sur l'utilisateur. Je suppose que c'est correct à utiliser si le fragment montre des informations en lecture seule. Ou même s'ils affichent des informations éditables, utilisez les méthodes de callbacks pour conserver les informations éditées.

  2. juste après la transaction est commit (vous venez d'appeler commit() ), passer un appel à FragmentManager.executePendingTransactions() .

voies non recommandées:

  1. comme Ovidiu Latcu mentionné ci-dessus, ne pas appeler super.onSaveInstanceState() . Mais cela signifie que vous perdrez tout l'état de votre activité ainsi que l'état des fragments.

  2. Remplacer onBackPressed et il appelle seulement finish() . Cela devrait être correct 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 que l'état de votre activité est important/vital, alors vous pouvez essayer d'appeler en utilisant L'API réflexion FragmentManagerImpl#noteStateNotSaved() . Mais c'est un piratage, ou on pourrait dire que c'est un contournement. Je n'aime pas ça, mais dans mon cas c'est assez acceptable puisque j'ai un code d'une application héritée qui utilise un code déprécié ( TabActivity et implicitement LocalActivityManager ).

ci-dessous est le code qui utilise la réflexion:

@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);
    }
}

santé!

72
répondu gunar 2014-03-24 07:44:47

une telle exception se produira si vous essayez d'effectuer une transition de fragment après que onSaveInstanceState() de votre activité de fragment soit appelé.

une des raisons pour lesquelles cela peut se produire, c'est que vous quittez un AsyncTask (ou Thread ) en cours d'exécution lorsqu'une activité est arrêtée.

n'importe quelle transition après onSaveInstanceState() est appelé pourrait potentiellement se perdre si le système réclame l'activité pour les ressources et le recrée plus tard.

33
répondu FunkTheMonk 2012-10-30 12:17:24

appelez simplement super.onPostResume () avant de montrer votre fragment ou déplacez votre code dans la méthode onPostResume () après avoir appelé super.onPostResume (). Ce résoudre le problème!

26
répondu MJ.Ahmadi 2013-09-16 09:20:26

cela peut aussi se produire lorsque l'on appelle dismiss() sur un fragment de dialogue après que l'écran a été verrouillé\blanked et que l'état d'instance de la boîte de dialogue Activity + a été sauvegardé. Pour contourner cet appel:

dismissAllowingStateLoss()

littéralement chaque fois que je rejette un dialogue, Je ne me soucie plus de son état de toute façon, donc c'est ok à faire - vous n'êtes pas en train de perdre un État.

18
répondu Brian Dilley 2013-10-22 23:22:59

solution courte et efficace:

Suivez Les Étapes Simples:

Étape 1 : outrepasser l'état onSaveInstanceState dans le fragment respectif. Et supprimer la méthode super.

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

Étape 2 : utiliser CommitAllowingStateLoss(); au lieu de commit(); pendant les opérations de fragment.

fragmentTransaction.commitAllowingStateLoss();
17
répondu Basbous 2014-09-05 14:26:48

ça a marché pour moi... trouvé ceci sur mon propre... espère que cela vous aide!

1) n'ont pas de gestionnaire de fragmentation /transaction de fragmentation global "statique".

2) onCreate, TOUJOURS initialiser le FragmentManager de nouveau!

é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();
    }
}
7
répondu kurayami88 2013-04-19 08:45:02

j'ai toujours eu cela quand j'ai essayé de montrer fragment dans la méthode onActivityForResult (), donc le problème était le suivant:

  1. mon activité est interrompue et arrêtée, ce qui signifie que onSaveInstanceState() a déjà été appelé (pour les dispositifs pré-nid d'abeille et post-nid d'abeille).
  2. dans le cas d'un résultat que j'ai fait transaction pour afficher/cacher fragment, ce qui provoque cette Illégalstateexception.

ce que j'ai fait est le suivant:

  1. valeur ajoutée pour déterminer si l'action que je veux a été fait (par exemple prendre une photo de camere - isPhotoTaken) - il peut être valeur booléenne ou entière en fonction de combien de transactions différentes vous avez besoin.
  2. dans la méthode overriden onResumeFragments () j'ai vérifié ma valeur et après avoir effectué des transactions de fragment j'ai eu besoin. Dans ce cas, commit() n'a pas été fait après onSaveInstanceState, puisque l'État a été retourné dans la méthode onResumeFragments ().
6
répondu Array 2014-09-06 12:39:23

j'ai résolu le problème avec onconfigurationchanged. L'astuce est que selon le cycle de vie de l'activité android, lorsque vous explicitement appelé une intention (intention caméra, ou tout autre); l'activité est en pause et onsavedInstance est appelé dans ce cas. Lors de la rotation du dispositif à une position différente de celle pendant laquelle l'activité était active; effectuer des opérations de fragment telles que fragment commit provoque une exception D'État illégale. Il y a beaucoup de plaintes à ce sujet. C'est quelque chose sur la gestion du cycle de vie de l'activité android et les appels de méthodes corrects. Pour le résoudre j'ai fait ceci: 1-Outrepassez 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 que votre activité ne soit interrompue. de cette façon, l'activité que vous verrouiller la rotation de l'écran pour votre activité dans le cas où il a été tourné par un autre. 2-alors , outrepassez la méthode onresume d'activité, et réglez votre mode d'orientation maintenant à capteur de sorte qu'après la méthode onsaved est appelé il appellera une fois de plus onconfiguration pour faire face à la rotation correctement.

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);
} 
5
répondu douggynix 2015-05-01 14:01:52

je pense que L'État de cycle de vie peut aider à prévenir un tel accident à partir de la prise en charge 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 ()

5
répondu Jamal 2018-01-11 23:36:02

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

le coupable était un appel au DialogFragment.montrer.)(

Je l'entoure de

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

et voilà. OK, je ne peux pas montrer le dialogue, mais dans ce cas, c'était parfait.

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

La chose drôle est, l'utilisateur ne quitte jamais l'application. Au lieu de ça, le tueur était une pub interstitielle de L'AdMob.

4
répondu Roger C S Wernersson 2015-04-09 07:40:25

ma solution pour ce problème était

dans le fragment ajouter les méthodes:

@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 je n'ai rien trouvé de mieux.

4
répondu mc.dev 2015-05-01 14:11:59

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 le commitAllowingStateLoss() sur la classe actuelle avec ce fragment.

4
répondu Peter 2017-02-20 09:15:31

onSaveInstance sera appelé si un utilisateur tourne l'écran de sorte qu'il puisse charger des ressources associées à la nouvelle orientation.

il est possible que cet utilisateur ait fait tourner l'écran puis ait appuyé sur le bouton arrière (parce qu'il est aussi possible que cet utilisateur ait brouillé son téléphone en utilisant votre application)

3
répondu dols 2011-12-26 22:22:44

j'ai eu ce numéro.Mais je pense que ce problème n'est pas lié à commit et commitowstatteloss.

le message de trace et d'exception suivant est à propos de 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 la réapparition du problème.

j'ai trouvé problème 25517

qu'Il pourrait avoir eu lieu dans les circonstances suivantes

  1. Back key est appelé après onSaveInstanceState, mais avant que la nouvelle activité est commencée.

  2. utiliser onStop () dans le code

Je ne sais pas quelle est la racine du problème. J'ai donc utilisé une vilaine façon.

@Override
public void onBackPressed() {

    try{
        super.onBackPressed();
    }catch (IllegalStateException e){
        // can output some information here
        finish();
    }
}
3
répondu oO_ox 2017-05-23 12:34:45

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

de l'article. fragment.isresumed () checking m'aide dans onDestroyView w / o en utilisant la méthode onSaveInstanceState.

2
répondu andep 2013-04-18 09:24:02

même numéro de ma part et après une journée d'analyse de tous les articles, blog et stackoverflow, j'ai trouvé une solution simple. N'utilisez pas savedInstanceState du tout, c'est la condition avec une ligne de code. Sur le code de fragment:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    .....
2
répondu Tobia Caneschi 2016-03-15 14:26:08

cela se produit chaque fois que vous essayez de charger un fragment mais que l'activité a changé son état en onPause().Cela se produit par exemple lorsque vous essayez de récupérer des données et de les charger dans l'activité, mais au moment où l'Utilisateur a cliqué sur un bouton et a déménagé à l'activité suivante.

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

vous pouvez utiliser transaction.commitallowingstatteloss () au lieu de transaction.commit() pour charger fragment, mais vous pourriez finir par perdre opération de validation qui est fait.

ou

assurez-vous que l'activité est dans le résumé et ne va pas à l'état de pause lors du chargement d'un fragment. Créer un booléen et vérifier 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();
}

ensuite, pendant le chargement, vérifier si l'activité est présente et ne charger que lorsque l'activité est à l'avant-plan.

if(mIsResumed){
 //load the fragment
}
2
répondu Anonymous 2017-09-27 09:58:18

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'utilisais des AlertDialogs et ProgressDialog comme fragments que, parfois, en rotation, en demandant le FragmentManager, l'erreur Monte.

j'ai trouvé une solution en mélangeant plusieurs messages similaires:

C'est une solution en 3 étapes, tout fait sur votre FragmentActivity (dans ce cas, son appelé Activité générale):

private static WeakReference<GenericActivity> 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<GenericActivity>(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();
}
0
répondu Antilope 2013-09-19 20:27:06

quand j'utilise startactivity dans un fragment, je vais obtenir cette exception;

quand je change pour utiliser startactivityforresult, l'exception est partie:)

la manière la plus simple de le corriger est d'utiliser l'api startActivityForResult:)

0
répondu Question 2013-12-20 06:32:52

j'ai eu cette exception quand j'ai appuyé sur le bouton arrière pour annuler le chooser d'intention sur mon activité de fragment de carte. J'ai résolu cela en remplaçant le code d'onResume()(où j'initialisais le fragment et commitais la transaction) par onStart() et l'application fonctionne bien maintenant. Espérons que cela aide.

0
répondu DCS 2014-07-14 11:44:15

c'est corrigé dans Android 4.2 et aussi dans la source de la bibliothèque de soutien.[ * ]

pour plus de détails sur la cause (et les solutions de rechange), reportez-vous au rapport de bogue de Google: http://code.google.com/p/android/issues/detail?id=19917

si vous utilisez la bibliothèque de support alors vous ne devriez pas avoir à vous soucier de ce bug (pour longtemps)[*]. Cependant, si vous utilisez l'API directement (C'est-à-dire que vous n'utilisez pas la bibliothèque FragmentManager) et ciblant une API sous Android 4.2, puis vous aurez besoin d'essayer l'une des solutions de rechange.

[ * ] au moment d'écrire le SDK Manager Android distribue toujours une ancienne version qui montre ce bug.

Edit je vais ajouter quelques clarifications ici parce que j'ai évidemment quelque peu confondu celui qui a voté cette réponse.

Il y a plusieurs (mais . 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 ensuite été corrigé. Si vous obtenez cette exception pour une autre raison, c'est parce que vous ajoutez/supprimez des fragments alors que vous ne devriez pas l'être (après que les états de fragments ont été sauvegardés). Si vous êtes dans une telle situation, alors peut-être " fragments emboîtés-IllegalStateException "ne peut pas effectuer cette action après onSaveInstanceState " " peut vous être utile.

0
répondu Benjamin Dobell 2017-05-23 12:10:44

après avoir cherché un peu la solution à ce problème est de faire votre fragment commits dans l'onresume.

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

0
répondu jai 2015-03-06 10:14:32

mon cas d'utilisation: j'ai utilisé l'auditeur dans fragment pour notifier l'activité qu'une chose est arrivée. J'ai fait un nouveau fragment de commit sur la méthode de callback. Cela fonctionne parfaitement bien sur la première fois. Mais sur le changement d'orientation l'activité est recréée avec l'état de l'instance sauvegardée. Dans ce cas fragment n'est pas créé à nouveau implique que le fragment ont l'auditeur qui est l'ancienne activité détruite. De n'importe quelle façon la méthode de rappel sera déclenchée sur l'action. Il va à l'activité détruite qui causent le question. La solution est de réinitialiser l'écouteur en fragment avec l'activité actuelle en direct. Ce résoudre le problème.

0
répondu Ganesh Kanna 2016-09-02 12:18:12

ce que j'ai trouvé est que si une autre application est le type de dialogue et permet que des touches soient envoyées à l'application d'arrière-plan, alors presque n'importe quelle application d'arrière-plan va planter avec cette erreur. Je pense que nous devons vérifier chaque fois qu'une transaction est effectuée si l'instance a été sauvée ou restaurée.

0
répondu chris 2016-10-04 05:00:27

dans mon cas, avec la même exception d'erreur, j'ai mis "onBackPressed()" dans une exécutable (Vous pouvez utiliser n'importe laquelle de vos vues):

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

je ne comprends pas pourquoi, mais ça fonctionne!

0
répondu Alecs 2017-02-08 15:42:19

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

0
répondu Murat 2017-04-24 14:40:09

Merci @gunar, mais je pense qu'il y a un meilleur moyen.

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();

utiliser commitNow pour remplacer:

fragmentTransaction.commit();
FragmentManager.executePendingTransactions()
0
répondu JianxinLi 2017-08-28 08:52:04

j'ai remarqué quelque chose de très intéressant. J'ai dans mon application l'option d'ouvrir la galerie du téléphone et l'appareil demande quelle application utiliser, là je clique sur la zone grise loin de la boîte de dialogue et j'ai vu ce problème. J'ai remarqué comment mon activité se déroule à partir de onPause, onSaveInstanceState de retour à onResume, il ne se trouve pas de visiter une visioncentrée. Je fais des transactions à onResume. Donc ce que j'ai fini par faire c'est de mettre un drapeau qui est nié à la pause, mais qui est vrai à la vue de treateview. si le drapeau est vrai onsume then do on commit, otherwise 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.

0
répondu Juan Mendez 2017-11-17 13:41:30

vous pouvez utiliser FragmentActivity.onStart avant popBackStackImmediate

comme ceci:

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

-1
répondu user3327339 2014-09-04 08:10:22