Status Update
Comments
da...@gmail.com <da...@gmail.com> #2
Hi. Thanks for reporting this. Fixed in alpha-04
co...@gmail.com <co...@gmail.com> #3
Branch: androidx-main
commit e782987543a9f8ccd485e970ddc74564b24378db
Author: Vighnesh Raut <vighnesh.raut13@gmail.com>
Date: Mon Jan 02 15:27:40 2023
fix: tab row crashes when only 1 tab is added
Bug:
Test: Added unit test
Change-Id: I6381dbac304fc1d69d3708c6655f8b595668e93f
M tv/tv-material/src/androidTest/java/androidx/tv/material/TabRowTest.kt
M tv/tv-material/src/main/java/androidx/tv/material/TabRow.kt
cl...@google.com <cl...@google.com>
an...@google.com <an...@google.com> #4
da...@gmail.com <da...@gmail.com> #5
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.tv:tv-material:1.0.0-alpha04
co...@gmail.com <co...@gmail.com> #6
I am also using navigation.
The provided workaround doesn't restore the mutation policy of the MutableState object.
an...@google.com <an...@google.com> #7
This one will save/restore the mutation policy as well:
fun <T> stateSaver() = listSaver<MutableState<T>, Any>(
save = { state ->
listOf(
state.value ?: "null",
when ((state as SnapshotMutableState).policy) {
structuralEqualityPolicy<T>() -> 0
referentialEqualityPolicy<T>() -> 1
neverEqualPolicy<T>() -> 2
else -> throw IllegalStateException("Mutation policy is not supported")
}
)
},
restore = {
val value = it[0]
val policy = when (it[1]) {
0 -> structuralEqualityPolicy<T>()
1 -> referentialEqualityPolicy<T>()
else -> neverEqualPolicy<T>()
}
@Suppress("UNCHECKED_CAST")
mutableStateOf((if (value == "null") null else value) as T, policy)
}
)
co...@gmail.com <co...@gmail.com> #8
What did you think of my solution that uses the init() function passed to the rememberSaveable()? This prevents needing to save anything about the policy and would support any mutation policy.
I'm not sure if the docs say anywhere that the init() function will only be called the first time and using it to restore the state would be incorrect.
I've been using my workaround fairly extensively and it has been great.
an...@google.com <an...@google.com> #9
Yes, this also works. Feel free to use it until we provide the correct fix in the library
ap...@google.com <ap...@google.com> #10
Branch: androidx-main
commit dd000ea5e6eb3a8f07b869595ca62aa2fb781d12
Author: Andrey Kulikov <andreykulikov@google.com>
Date: Mon Feb 22 19:42:13 2021
Fix for broken rememberSaveable { mutableStateOf(0) } with navigation-compose
Previously we were converting MutableState into a parcelable structure only for a direct child of the saving list. It was incorrect as SaveableStateHolder used in navigation is wrapping the state of the screen as a value into a Map. Now we will recursively iterate through List/Maps and covert all inner MutableState objects.
Fixes: 180042685
Fixes: 180701630
Test: new tests in ActivityRecreationTest
Relnote: Fix for broken rememberSaveable { mutableStateOf(0) } when used inside a destination of navigation-compose.
Change-Id: I1312b5b210dde32250945d164a2f3a1b574cb0a8
M compose/runtime/runtime-saveable/src/androidAndroidTest/AndroidManifest.xml
M compose/runtime/runtime-saveable/src/androidAndroidTest/kotlin/androidx/compose/runtime/saveable/ActivityRecreationTest.kt
M compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/DisposableSaveableStateRegistry.android.kt
an...@google.com <an...@google.com> #11
ba...@gmail.com <ba...@gmail.com> #12
It looks like this bug has been re-introduced in 1.0
an...@google.com <an...@google.com> #13
el...@kroger.com <el...@kroger.com> #14
Hi I am seeing this same issue using navigation-compose version 2.5.2, we tried the suggestions from this thread from 2021 but they did not work. The stack trace looks like this:
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = [Landroidx.compose.runtime.MutableState;)
at android.os.Parcel.writeSerializable(Parcel.java:1833)
at android.os.Parcel.writeValue(Parcel.java:1780)
at android.os.Parcel.writeList(Parcel.java:1045)
at android.os.Parcel.writeValue(Parcel.java:1729)
at android.os.Parcel.writeMapInternal(Parcel.java:896)
at android.os.Parcel.writeMap(Parcel.java:878)
at android.os.Parcel.writeValue(Parcel.java:1694)
at android.os.Parcel.writeMapInternal(Parcel.java:896)
at android.os.Parcel.writeMap(Parcel.java:878)
at android.os.Parcel.writeValue(Parcel.java:1694)
at android.os.Parcel.writeList(Parcel.java:1045)
at android.os.Parcel.writeValue(Parcel.java:1729)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584)
at android.os.Bundle.writeToParcel(Bundle.java:1253)
at android.os.Parcel.writeBundle(Parcel.java:997)
at android.os.Parcel.writeValue(Parcel.java:1698)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:928)
...
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4505)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.io.NotSerializableException: androidx.compose.runtime.ParcelableSnapshotMutableState
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1434)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1230)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
at android.os.Parcel.writeSerializable(Parcel.java:1828)
at android.os.Parcel.writeValue(Parcel.java:1780)
at android.os.Parcel.writeList(Parcel.java:1045)
at android.os.Parcel.writeValue(Parcel.java:1729)
at android.os.Parcel.writeMapInternal(Parcel.java:896)
at android.os.Parcel.writeMap(Parcel.java:878)
...
an...@google.com <an...@google.com> #15
If you can file a new bug with the reproducible code sample we will be able to take a look
ga...@gmail.com <ga...@gmail.com> #16
E FATAL EXCEPTION: main
Process: com.example.animeapp, PID: 12273
java.lang.RuntimeException: Parcel: unable to marshal value Color(0.83137256, 0.75686276, 0.8156863, 1.0, sRGB IEC61966-2.1)
at android.os.Parcel.writeValue(Parcel.java:1885)
at android.os.Parcel.writeList(Parcel.java:1092)
at android.os.Parcel.writeValue(Parcel.java:1832)
at android.os.Parcel.writeList(Parcel.java:1092)
at android.os.Parcel.writeValue(Parcel.java:1832)
at android.os.Parcel.writeMapInternal(Parcel.java:943)
at android.os.Parcel.writeMap(Parcel.java:925)
at android.os.Parcel.writeValue(Parcel.java:1797)
at android.os.Parcel.writeMapInternal(Parcel.java:943)
at android.os.Parcel.writeMap(Parcel.java:925)
at android.os.Parcel.writeValue(Parcel.java:1797)
at android.os.Parcel.writeList(Parcel.java:1092)
at android.os.Parcel.writeValue(Parcel.java:1832)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:975)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1303)
at android.os.Parcel.writeBundle(Parcel.java:1044)
at android.os.Parcel.writeValue(Parcel.java:1801)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:975)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1303)
at android.os.Parcel.writeBundle(Parcel.java:1044)
at android.os.Parcel.writeValue(Parcel.java:1801)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:975)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1303)
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4389)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
an...@google.com <an...@google.com> #17
ma...@marcardar.com <ma...@marcardar.com> #18
Related to this issue, it would be useful to give more details in the log message, because when, for example, the object is a Set
we have no idea what is the underlying type (the type of the items stored in the Set
) and so have no idea where to look in the code:
Fatal Exception: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = java.util.LinkedHashSet)
at android.os.Parcel.writeSerializable(Parcel.java:2178)
at android.os.Parcel.writeValue(Parcel.java:1944)
at androidx.compose.runtime.ParcelableSnapshotMutableState.writeToParcel(ParcelableSnapshotMutableState.kt:30)
at android.os.Parcel.writeParcelable(Parcel.java:1965)
at android.os.Parcel.writeValue(Parcel.java:1871)
at android.os.Parcel.writeList(Parcel.java:1153)
at android.os.Parcel.writeValue(Parcel.java:1893)
at android.os.Parcel.writeMapInternal(Parcel.java:1004)
at android.os.Parcel.writeMap(Parcel.java:986)
at android.os.Parcel.writeValue(Parcel.java:1858)
at android.os.Parcel.writeMapInternal(Parcel.java:1004)
at android.os.Parcel.writeMap(Parcel.java:986)
at android.os.Parcel.writeValue(Parcel.java:1858)
at android.os.Parcel.writeList(Parcel.java:1153)
at android.os.Parcel.writeValue(Parcel.java:1893)
at android.os.Parcel.writeMapInternal(Parcel.java:1004)
at android.os.Parcel.writeMap(Parcel.java:986)
at android.os.Parcel.writeValue(Parcel.java:1858)
at android.os.Parcel.writeList(Parcel.java:1153)
at android.os.Parcel.writeValue(Parcel.java:1893)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:1036)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1620)
at android.os.Bundle.writeToParcel(Bundle.java:1304)
at android.os.Parcel.writeBundle(Parcel.java:1105)
at android.os.Parcel.writeValue(Parcel.java:1862)
at android.os.BaseBundle.dumpStats(BaseBundle.java:1690)
at android.os.BaseBundle.dumpStats(BaseBundle.java:1727)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:150)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
il...@google.com <il...@google.com> #19
Re
Description
Component used: Compose Version used: 1.0.0-alpha12 Devices/Android versions reproduced on: Pixel 4 Android 11
The recommended code to replace
savedInstanceState{ 0 }
isrememberSaveable { mutableStateOf(0) }
However, I've found this causes a crash whenever the app is minimized.
The exception thrown is
java.lang.RuntimeException: Parcel: unable to marshal value androidx.compose.runtime.SnapshotMutableStateImpl@5a847c2
After digging into the code I believe this is caused by the special version of
rememberSaveable
forMutableState
objects doesn't have a default saver parameter so the normal version is used which doesn't know how to save aMutableState
.I think changing the
rememberSaveable
definition fromto
would fix this.