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)
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èsonPause()
sur pre-Honeycomb, etonStop()
sur post-Honeycomb - soyez prudent lorsque vous effectuez des transactions à l'intérieur des méthodes du cycle de vie
Activity
. UtilisationonCreate()
,onResumeFragments()
etonPostResume()
- Evite d'effectuer des transactions à l'intérieur des méthodes de rappel asynchrones
- utiliser
commitAllowingStateLoss()
en dernier recours seulement
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èresavant toute autre chose: je voudrais annoncer Alex Lockwood article . Puis, de ce que j'ai fait jusqu'à présent:
-
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.
-
juste après la transaction est commit (vous venez d'appeler
commit()
), passer un appel àFragmentManager.executePendingTransactions()
.
voies non recommandées:
-
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. -
Remplacer
onBackPressed
et il appelle seulementfinish()
. Cela devrait être correct si votre application n'utilise pas L'API Fragments; comme danssuper.onBackPressed
il y a un appel àFragmentManager#popBackStackImmediate()
. -
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 implicitementLocalActivityManager
).
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é!
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.
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!
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.
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();
ç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();
}
}
j'ai toujours eu cela quand j'ai essayé de montrer fragment dans la méthode onActivityForResult (), donc le problème était le suivant:
- 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).
- 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:
- 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.
- 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 ().
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);
}
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 ()
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.
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.
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.
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)
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
-
Back key est appelé après onSaveInstanceState, mais avant que la nouvelle activité est commencée.
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();
}
}
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.
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);
.....
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
}
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();
}
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:)
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.
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.
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 /
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.
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.
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!
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().
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()
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.
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