Fixed
Status Update
Comments
yb...@google.com <yb...@google.com> #2
Hi Ed, Thank you so much for these suggestions. I've been reviewing them and merging them in. Hopefully it should be live. I've included a thank you note too in the article.
yb...@google.com <yb...@google.com> #3
Great! Thanks a lot, I'll look for the live updates soon!
ni...@gmail.com <ni...@gmail.com> #4
Yes, it's the right lifecycle. I'm using LiveData as a singleton, I know it's not 100% accepted, but I thought it would work (am I wrong?).... In onCreate() I observe the livedata like this:
ayudanteDePagos = AyudanteDePagos.dameInstancia(this); // in English: paymentHelper = PaymentHelper.getInstance(this);
ayudanteDePagos.observe(this, this::esPro);
esPro() is an instance method, that eventually tries to perform a fragment transaction (calls a static method "mostrar()' passing "this" as a parameter). I can't find anything wrong here.
ayudanteDePagos = AyudanteDePagos.dameInstancia(this); // in English: paymentHelper = PaymentHelper.getInstance(this);
ayudanteDePagos.observe(this, this::esPro);
esPro() is an instance method, that eventually tries to perform a fragment transaction (calls a static method "mostrar()' passing "this" as a parameter). I can't find anything wrong here.
se...@google.com <se...@google.com> #5
that looks weird and looks like fragments bug. From your stacktrace we can see "Activity.performResume", so we should be able to run commits on fragmentmanager of that activity. Do you use fragmentmanager of that activity or do you have nested fragments and this is fragment manager of parent fragment?
ni...@gmail.com <ni...@gmail.com> #6
Sorry for the late reply. No, I don't have nested fragments here.
I'm seeing in crashlytics a similar stacktrace, this one:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
androidx.fragment.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:2080)
androidx.fragment.app.FragmentManagerImpl.enqueueAction (FragmentManager.java:2106)
androidx.fragment.app.FragmentManagerImpl.popBackStack (FragmentManager.java:832)
ar.com.lichtmaier.antenas.CalibrarBrújulaFragment.mostrarUOcultar (CalibrarBrújulaFragment.java:30)
ar.com.lichtmaier.antenas.AntenaActivity.lambda$onCreate$0 (AntenaActivity.java:153)
ar.com.lichtmaier.antenas.-$$Lambda$AntenaActivity$ve3bG1806pSgUYbnwt42o2eiiok.onChanged (lambda)
androidx.lifecycle.LiveData.considerNotify (LiveData.java:113)
androidx.lifecycle.LiveData.dispatchingValue (LiveData.java:126)
androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged (LiveData.java:424)
androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged (LiveData.java:376)
androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.java:355)
androidx.lifecycle.LifecycleRegistry.forwardPass (LifecycleRegistry.java:293)
androidx.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.java:333)
androidx.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.java:138)
androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.java:124)
androidx.lifecycle.ReportFragment.dispatch (ReportFragment.java:122)
androidx.lifecycle.ReportFragment.onResume (ReportFragment.java:89)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:879)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1038)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1020)
android.app.FragmentManagerImpl.dispatchResume (FragmentManager.java:1784)
android.app.Activity.performResume (Activity.java:4681)
[...]
I'm using a LiveData to store the state of the compass (calibrated | not calibrated). I subscribe to it like this;
viewModel.brújula.faltaCalibrar.observe(this, descalibrada -> CalibrarBrújulaFragment.mostrarUOcultar(this, descalibrada != null && descalibrada));
then "mostrarUOcultar" (show or hide) starts like this:
public static void mostrarUOcultar(FragmentActivity activity, boolean mostrar)
{
if(!mostrar)
{
activity.getSupportFragmentManager().popBackStack(FRAGMENT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); // crashes here!
return;
}
I'm using the activity's fragment manager. I guess that should be ok, but I'm mentioning just in case.
I'm seeing in crashlytics a similar stacktrace, this one:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
androidx.fragment.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:2080)
androidx.fragment.app.FragmentManagerImpl.enqueueAction (FragmentManager.java:2106)
androidx.fragment.app.FragmentManagerImpl.popBackStack (FragmentManager.java:832)
ar.com.lichtmaier.antenas.CalibrarBrújulaFragment.mostrarUOcultar (CalibrarBrújulaFragment.java:30)
ar.com.lichtmaier.antenas.AntenaActivity.lambda$onCreate$0 (AntenaActivity.java:153)
ar.com.lichtmaier.antenas.-$$Lambda$AntenaActivity$ve3bG1806pSgUYbnwt42o2eiiok.onChanged (lambda)
androidx.lifecycle.LiveData.considerNotify (LiveData.java:113)
androidx.lifecycle.LiveData.dispatchingValue (LiveData.java:126)
androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged (LiveData.java:424)
androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged (LiveData.java:376)
androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.java:355)
androidx.lifecycle.LifecycleRegistry.forwardPass (LifecycleRegistry.java:293)
androidx.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.java:333)
androidx.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.java:138)
androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.java:124)
androidx.lifecycle.ReportFragment.dispatch (ReportFragment.java:122)
androidx.lifecycle.ReportFragment.onResume (ReportFragment.java:89)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:879)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1038)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1020)
android.app.FragmentManagerImpl.dispatchResume (FragmentManager.java:1784)
android.app.Activity.performResume (Activity.java:4681)
[...]
I'm using a LiveData to store the state of the compass (calibrated | not calibrated). I subscribe to it like this;
viewModel.brújula.faltaCalibrar.observe(this, descalibrada -> CalibrarBrújulaFragment.mostrarUOcultar(this, descalibrada != null && descalibrada));
then "mostrarUOcultar" (show or hide) starts like this:
public static void mostrarUOcultar(FragmentActivity activity, boolean mostrar)
{
if(!mostrar)
{
activity.getSupportFragmentManager().popBackStack(FRAGMENT_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE); // crashes here!
return;
}
I'm using the activity's fragment manager. I guess that should be ok, but I'm mentioning just in case.
se...@google.com <se...@google.com> #7
Yeah we don't support framework fragments and this guarantee isn't true for them (they have a bit different behavior once it comes to lifecycle methods). Framework fragments were deprecated, so please move to support library ones.
ni...@gmail.com <ni...@gmail.com> #8
What? I'm not using framework fragments anywhere. This is just an activity ("AntenaActivity", extends AppCompatActivity) with no fragments that tries to hide/show a fragment extending AppCompatDialogFragment, and as you can see in the code snippet I'm correctly calling getSupportFragmentManager().
se...@google.com <se...@google.com> #9
Ah sorry I misread your stacktrace.
se...@google.com <se...@google.com> #10
+ Ian,
Ian, do you have any ideas why we may fail to run fragment transaction in onResume?
Ian, do you have any ideas why we may fail to run fragment transaction in onResume?
ni...@gmail.com <ni...@gmail.com> #11
Yeah, some platform fragment things appear there in the stack, but that seems to be something the activity calls whether you use platform fragments or not. Thank you for reopening this.
se...@google.com <se...@google.com> #12
Ok, I was able to reproduce it. The issue is FragmentActivity.onResume doesn't resume its fragments and allow transactions immediately.
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 9823ca6d8057b27adb44c8ffd3f211191bb41963
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Thu Aug 23 18:41:17 2018
Call noteStateNotSaved() in OnResume
bug: 77944637
Test: SafeTransactionInOnResumeTest
Change-Id: I13211e0fece639382c8e3e961a8c702519d1c051
M fragment/build.gradle
M fragment/src/androidTest/AndroidManifest.xml
A fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt
M fragment/src/androidTest/res/values/styles.xml
M fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
https://android-review.googlesource.com/737285
https://goto.google.com/android-sha1/9823ca6d8057b27adb44c8ffd3f211191bb41963
Branch: androidx-master-dev
commit 9823ca6d8057b27adb44c8ffd3f211191bb41963
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Thu Aug 23 18:41:17 2018
Call noteStateNotSaved() in OnResume
bug: 77944637
Test: SafeTransactionInOnResumeTest
Change-Id: I13211e0fece639382c8e3e961a8c702519d1c051
M fragment/build.gradle
M fragment/src/androidTest/AndroidManifest.xml
A fragment/src/androidTest/java/androidx/fragment/app/SafeTransactionInOnResumeTest.kt
M fragment/src/androidTest/res/values/styles.xml
M fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
se...@google.com <se...@google.com> #14
So it is fixed, however, I'm not sure in what release it will go in 1.0.0-rc03 or 1.1.0
ni...@gmail.com <ni...@gmail.com> #15
Thanks a lot!
[Deleted User] <[Deleted User]> #16
Am I correct that the bug will be fixed only for AndroidX? Does this mean that we need to migrate our codebase to AndroidX in order to rely on LiveData not lead to IllegalStateException: Can not perform this action after onSaveInstanceState?
ni...@gmail.com <ni...@gmail.com> #17
This is the number one issue crashing my app. Can't the fix be released in a rc? Will I need to wait to 1.1.0? =/
zh...@gmail.com <zh...@gmail.com> #18
Use `commitAllowingStateLoss()`, it is the only safe way to commit a fragment transaction.
Description
Version used:1.1.1
Devices/Android versions reproduced on: Android 4.x and 5.x
This is not something I can reproduce, but I'm seeing many errors in Crashlytics.
LiveData is supposed to notify changes only when it's safe to do fragment transactions, so this should not be happening, if I understand it correctly.
This is one of the exceptions I'm seeing:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
android.support.v4.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:2055)
android.support.v4.app.FragmentManagerImpl.enqueueAction (FragmentManager.java:2078)
android.support.v4.app.BackStackRecord.commitInternal (BackStackRecord.java:678)
android.support.v4.app.BackStackRecord.commit (BackStackRecord.java:632)
android.support.v4.app.DialogFragment.show (DialogFragment.java:160)
ar.com.lichtmaier.antenas.Pagame.mostrar (Pagame.java:33)
ar.com.lichtmaier.antenas.AntenaActivity.esPro (AntenaActivity.java:708)
ar.com.lichtmaier.antenas.AntenaActivity.bridge$lambda$0$AntenaActivity (AntenaActivity.java)
ar.com.lichtmaier.antenas.AntenaActivity$$Lambda$0.onChanged (Unknown Source)
android.arch.lifecycle.LiveData.considerNotify (LiveData.java:109)
android.arch.lifecycle.LiveData.dispatchingValue (LiveData.java:121)
android.arch.lifecycle.LiveData.access$400 (LiveData.java:59)
android.arch.lifecycle.LiveData$ObserverWrapper.activeStateChanged (LiveData.java:416)
android.arch.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged (LiveData.java:368)
android.arch.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.java:354)
android.arch.lifecycle.LifecycleRegistry.forwardPass (LifecycleRegistry.java:292)
android.arch.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.java:332)
android.arch.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.java:137)
android.arch.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.java:123)
android.arch.lifecycle.ReportFragment.dispatch (ReportFragment.java:121)
android.arch.lifecycle.ReportFragment.onResume (ReportFragment.java:88)
android.app.Fragment.performResume (Fragment.java:2096)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:928)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1067)
android.app.FragmentManagerImpl.moveToState (FragmentManager.java:1049)
android.app.FragmentManagerImpl.dispatchResume (FragmentManager.java:1879)
android.app.Activity.performResume (Activity.java:6128)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:2995)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3037)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1350)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:135)
android.app.ActivityThread.main (ActivityThread.java:5290)
java.lang.reflect.Method.invoke (Method.java)
java.lang.reflect.Method.invoke (Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:911)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:706)