Fixed
Status Update
Comments
ia...@google.com <ia...@google.com> #2
I see same issue and have been debugging it.
NOTE: It DOES NOT happen if not using support package, but use android level 14/15 library. I believe Honeycomb works well too.
My current workaround is to provide my own DialogFragment.show() method, like below:
public int show(FragmentTransaction transaction, String tag) {
return show(transaction, tag, false);
}
public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) {
transaction.add(this, tag);
mRemoved = false;
mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit();
return mBackStackId;
}
NOTE: It DOES NOT happen if not using support package, but use android level 14/15 library. I believe Honeycomb works well too.
My current workaround is to provide my own DialogFragment.show() method, like below:
public int show(FragmentTransaction transaction, String tag) {
return show(transaction, tag, false);
}
public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) {
transaction.add(this, tag);
mRemoved = false;
mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit();
return mBackStackId;
}
an...@gmail.com <an...@gmail.com> #3
[Comment deleted]
an...@airbnb.com <an...@airbnb.com> #4
But Google pls fix this issue, as the expected behaviors must be consistent with ICS DialogFragment + FragmentManager and support package DialogFragment + FragmentManager.
It happens with both Support Package v4 r6 and v13 r6.
It happens with both Support Package v4 r6 and v13 r6.
pe...@airbnb.com <pe...@airbnb.com> #5
I have this problem too.
As a workaround I use a boolean in the onActivityResult to mark the desired dialog and show the dialog in the onResume.
As a workaround I use a boolean in the onActivityResult to mark the desired dialog and show the dialog in the onResume.
lo...@gmail.com <lo...@gmail.com> #7
This is definitely not a bug. There are times when onActivityResult() can be called before the Activity has restored its saved state... committing fragment transactions in these situations will simply not be remembered as a result (see this blog post: http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html ).
Try moving your commits into "onPostResume()" instead as described here:http://stackoverflow.com/questions/16265733/failure-delivering-result-onactivityforresult/18345899#18345899
Try moving your commits into "onPostResume()" instead as described here:
ch...@gmail.com <ch...@gmail.com> #8
Adding a "super.onActivityResult(requestCode, resultCode, data)" call at the beginning of the method seems to fix the problem. I'm surprised than almost nobody came up with such a simple solution.
an...@gmail.com <an...@gmail.com> #9
Dear alockw...@google.com,
Let's say we have an application where we need to select a picture from gallery, and then when we come back to onActivityResult(), we need to show a DialogFragment asking the user if he really wants to send the file.
How do you propose we can implement this with the current API?
Thank you,
Sabin
Let's say we have an application where we need to select a picture from gallery, and then when we come back to onActivityResult(), we need to show a DialogFragment asking the user if he really wants to send the file.
How do you propose we can implement this with the current API?
Thank you,
Sabin
vi...@google.com <vi...@google.com> #10
Please also consider how to deal with "Avoid performing transactions inside asynchronous callback methods." problem which is stated in http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html#more
dismissAllowingStateLoss() is the least resort for dismiss() dialog in onPostExecute(), but there is no solution for DialogFragment#show() in onPreExecute() callback.
dismissAllowingStateLoss() is the least resort for dismiss() dialog in onPostExecute(), but there is no solution for DialogFragment#show() in onPreExecute() callback.
qw...@gmail.com <qw...@gmail.com> #11
I have a similar problem, but I show the DialogFragment (not the one of the support library) on the onStart method call.
How could it be? And, how can I solve this?
How could it be? And, how can I solve this?
qw...@gmail.com <qw...@gmail.com> #13
public void showAllowingStateLoss(FragmentManager manager, String tag) {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
}
I looked up the source code and got this method. I'm wondering why Google add a @hide annotation to this great API?
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
}
I looked up the source code and got this method. I'm wondering why Google add a @hide annotation to this great API?
lo...@gmail.com <lo...@gmail.com> #15
Just looked up source code and this method was introduced since API 23. So maybe here's another alternative:
getFragmentManager().beginTransaction()
.add(fragment, tag)
.commitAllowingStateLoss();
getFragmentManager().beginTransaction()
.add(fragment, tag)
.commitAllowingStateLoss();
ng...@google.com <ng...@google.com> #16
Oh my god..
This error happened to my app users..
Please refer to below logs.
Samsung Galaxy Note10+ 5G (d2x), Android 9
java.lang.IllegalStateException:
at androidx.fragment.app.FragmentManager.checkStateLoss (FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.enqueueAction (FragmentManager.java:2029)
at androidx.fragment.app.BackStackRecord.commitInternal (BackStackRecord.java:321)
at androidx.fragment.app.BackStackRecord.commit (BackStackRecord.java:286)
at androidx.fragment.app.DialogFragment.show (DialogFragment.java:156)
at com.xxx.yyyyy.ZZZActivity$8$1.run (ZZZActivity.java:585)
at android.os.Handler.handleCallback (Handler.java:873)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:216)
at android.app.ActivityThread.main (ActivityThread.java:7263)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
This error happened to my app users..
Please refer to below logs.
Samsung Galaxy Note10+ 5G (d2x), Android 9
java.lang.IllegalStateException:
at androidx.fragment.app.FragmentManager.checkStateLoss (FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.enqueueAction (FragmentManager.java:2029)
at androidx.fragment.app.BackStackRecord.commitInternal (BackStackRecord.java:321)
at androidx.fragment.app.BackStackRecord.commit (BackStackRecord.java:286)
at androidx.fragment.app.DialogFragment.show (DialogFragment.java:156)
at com.xxx.yyyyy.ZZZActivity$8$1.run (ZZZActivity.java:585)
at android.os.Handler.handleCallback (Handler.java:873)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loop (Looper.java:216)
at android.app.ActivityThread.main (ActivityThread.java:7263)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
lo...@gmail.com <lo...@gmail.com> #17
This issue never reproduced/happened on Android 11 and lower, right?
ng...@google.com <ng...@google.com> #18
I don't think so.
pe...@meta.com <pe...@meta.com> #19
how this fix be rollout for the ART? anything we can check on the device?
Description
We started experiencinghttps://github.com/Kotlin/kotlinx.coroutines/issues/3820 in our app (Only in Android 12 and 13 so far, but currently this is just in beta) and after some investigation I think that this could be some issue with the Android Runtime or the GC. Let me share here the same step by step analysis that I already shared in the Coroutines issue:
The crash originates in
StateFlowSlot.makePending()
which before theatomicfu
update looked like this (this is decompiled Android byte code to Java:Note: The crash did not happen in this case.
After the update to
atomicfu
in 1.7.0 it looks like this:with the crash originating in this line:
Object obj = atomicReferenceFieldUpdater.get(this);
Note: Even though
StateFlow.kt
had no meaningful code change between 1.6.4 and 1.7.0 because of theatomicfu
update the byte code changed. This is also the reason why the forced dependency downgrade ofatomicfu
will not "fix" this issue, as the impacted code is already in the coroutines-core
.jar
file. So the downgrade during app build does not really do anything anymore.This is where it gets funky: This code calls
get
onAtomicReferenceFieldUpdaterImpl
withthis
(StateFlowSlot
) instance as parameter.with
cclass
isStateFlowSlot.class
because it is the first parameter inand the constructor of
AtomicReferenceFieldUpdaterImpl
assigns it to thetclass
, which is the fist parameter:so this
accessCheck
is checking if our instance of typeStateFlowSlot
is an instance ofStateFlowSlot.class
on Android 13 the
isInstance
call looks like this:so this will get the
class
from the object (which itself is notnull
) that we called this with (which would be the existing instance ofStateFlowSlow
.into
And this is where the crash is in line
if (!cls.isInterface()) {
.Which means that the
obj.getClass()
call inisInstance
returned anull
class even though the instance is not null, which leads to that crash and seems to be an impossible state to be in (the Class of a live instance is null).The
Object
implementation on Android seems to use some kind of backing field here:which must be
null
in this case. Given that this is happening way less often than this code is getting called it appears that this is some kind of race condition, maybe with GC but I really don't know any further.Android standard lib code examples from:https://android.googlesource.com/platform/libcore/+/refs/heads/android13-d1-release/ojluni/src/main/java/java/lang