Fixed
Status Update
Comments
il...@google.com <il...@google.com>
nd...@gmail.com <nd...@gmail.com> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
st...@gmail.com <st...@gmail.com> #3
yea i'll take it.
ap...@google.com <ap...@google.com> #4
Thanks for the detailed analysis. This may not be an issue anymore since we've started using Main.immediate there but I' not sure; I'll try to create a test case.
cl...@google.com <cl...@google.com> #5
just emitting same live data reproduces the issue.
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
st...@gmail.com <st...@gmail.com> #6
With 2.2.0-alpha04 (that use Main.immediate), the issue seems to be still there (I tested it by calling emitSource() twice, like your test case)
st...@gmail.com <st...@gmail.com> #7
yea sorry immediate does not fix it.
I actually have a WIP fix for it:
https://android-review.googlesource.com/c/platform/frameworks/support/+/1112186
if your case is the one i found (emitting same LiveData multiple times, as shown in #5) you can work around it by adding a dummy transformation.
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData.map {it })
emitSource(subLiveData.map {it} )
}
I actually have a WIP fix for it:
if your case is the one i found (emitting same LiveData multiple times, as shown in #5) you can work around it by adding a dummy transformation.
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData.map {it })
emitSource(subLiveData.map {it} )
}
cl...@google.com <cl...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-master-dev
commit af12e75e6b4110f48e44ca121466943909de8f06
Author: Yigit Boyar <yboyar@google.com>
Date: Tue Sep 03 12:58:11 2019
Fix coroutine livedata race condition
This CL fixes a bug in liveData builder where emitting same
LiveData source twice would make it crash because the second
emission registry could possibly happen before first one is
removed as source.
We fix it by using a suspending dispose function. It does feel
a bit hacky but we cannot make DisposableHandle.dispose async
and we do not want to block there. This does not mean that there
is a problem if developer disposes it manually since our emit
functions take care of making sure it disposes (and there is
no other way to add source to the underlying MediatorLiveData)
Bug: 140249349
Test: BuildLiveDataTest#raceTest_*
Change-Id: I0b464c242a583da4669af195cf2504e2adc4de40
M lifecycle/lifecycle-livedata-ktx/api/2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/current.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
M lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
M lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
https://android-review.googlesource.com/1112186
https://goto.google.com/android-sha1/af12e75e6b4110f48e44ca121466943909de8f06
Branch: androidx-master-dev
commit af12e75e6b4110f48e44ca121466943909de8f06
Author: Yigit Boyar <yboyar@google.com>
Date: Tue Sep 03 12:58:11 2019
Fix coroutine livedata race condition
This CL fixes a bug in liveData builder where emitting same
LiveData source twice would make it crash because the second
emission registry could possibly happen before first one is
removed as source.
We fix it by using a suspending dispose function. It does feel
a bit hacky but we cannot make DisposableHandle.dispose async
and we do not want to block there. This does not mean that there
is a problem if developer disposes it manually since our emit
functions take care of making sure it disposes (and there is
no other way to add source to the underlying MediatorLiveData)
Bug: 140249349
Test: BuildLiveDataTest#raceTest_*
Change-Id: I0b464c242a583da4669af195cf2504e2adc4de40
M lifecycle/lifecycle-livedata-ktx/api/2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/current.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
M lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
M lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
cl...@google.com <cl...@google.com> #9
Ah yes I see the crash in release build. As Ian recommended, use @androidx.annotation.Keep
or else the class gets removed.
st...@gmail.com <st...@gmail.com> #10
Created a new issue
ap...@google.com <ap...@google.com> #11
Project: platform/frameworks/support
Branch: androidx-main
commit 6187e05a8c1892c1679aa4571e5a5d6ffb9663e8
Author: Clara Fok <clarafok@google.com>
Date: Fri Aug 09 09:26:44 2024
Improve error message for Enum type
Navigation added built-in support for Enums in type safety. Due to limited metadata without kotlin reflect, the implementation relies on the Enum's serialName to match the Enum class's fqn.
However, if r8 minifed build is employed in release builds, it is possible that the fqn is modified. Kotlinx serialization is not aware of this, however, and the serialName would remain the same. This means navigation won't be able to match the serialName to the new fqn.
The current solution is to add @androidx.annotation.Keep on enum classes to ensure it doesn't get erased. We should update the exception message to suggest this as a possible solution.
Test: ./gradlew navigation:navigation-common:cC
Bug: 358137294
Relnote: "Update Enum class not found exception to suggest using @Keep annotation in case the Enum class gets erased in minified builds."
Change-Id: I90e79cc476c21ab0ad3b172af65c436817665ef7
M navigation/navigation-common/src/main/java/androidx/navigation/serialization/NavTypeConverter.kt
M navigation/navigation-common/src/test/java/androidx/navigation/serialization/NavArgumentGeneratorTest.kt
https://android-review.googlesource.com/3214157
Branch: androidx-main
commit 6187e05a8c1892c1679aa4571e5a5d6ffb9663e8
Author: Clara Fok <clarafok@google.com>
Date: Fri Aug 09 09:26:44 2024
Improve error message for Enum type
Navigation added built-in support for Enums in type safety. Due to limited metadata without kotlin reflect, the implementation relies on the Enum's serialName to match the Enum class's fqn.
However, if r8 minifed build is employed in release builds, it is possible that the fqn is modified. Kotlinx serialization is not aware of this, however, and the serialName would remain the same. This means navigation won't be able to match the serialName to the new fqn.
The current solution is to add @androidx.annotation.Keep on enum classes to ensure it doesn't get erased. We should update the exception message to suggest this as a possible solution.
Test: ./gradlew navigation:navigation-common:cC
Bug: 358137294
Relnote: "Update Enum class not found exception to suggest using @Keep annotation in case the Enum class gets erased in minified builds."
Change-Id: I90e79cc476c21ab0ad3b172af65c436817665ef7
M navigation/navigation-common/src/main/java/androidx/navigation/serialization/NavTypeConverter.kt
M navigation/navigation-common/src/test/java/androidx/navigation/serialization/NavArgumentGeneratorTest.kt
na...@google.com <na...@google.com> #12
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-common:2.8.0-rc01
androidx.navigation:navigation-runtime:2.8.0-rc01
sa...@outlook.com <sa...@outlook.com> #13
This bug is not happening for me anymore with the debug build, but is still happening with the release/R8 minified build.
Looks like the above suggestion to update the exception to add the Keep annotation would be a good idea.
Looks like the above suggestion to update the exception to add the Keep annotation would be a good idea.
ch...@gmail.com <ch...@gmail.com> #14
I'm building my app in debug with minify disabled but I still have the issue:
@Serializable
data class NewReservationDetails(val usage: Usage) {
companion object {
val typeMap = mapOf(typeOf<Usage>() to NavType.EnumType<Usage>(Usage::class.java))
fun from(savedStateHandle: SavedStateHandle) =
savedStateHandle.toRoute<Usage>(typeMap)
}
}
composable<NewReservationDetails>(
enterTransition = { expandHorizontally() },
exitTransition = { shrinkHorizontally() },
typeMap = NewReservationDetails.typeMap
) { backStackEntry ->
val parentEntry = remember(backStackEntry) {
navController.getBackStackEntry(NewReservation)
}
val parentViewModel: OrderRideHostViewModel = hiltViewModel(parentEntry)
val viewModel: OrderRideAddressDateViewModel = hiltViewModel()
NewReservationDetailsScreen(
orderRideAddressDateViewModel = viewModel,
orderRideHostViewModel = parentViewModel
)
}
)
class OrderRideAddressDateViewModel @Inject constructor(
val savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val usage = NewReservationDetails.from(savedStateHandle)
}
I'm still having the crash, i've tried a lot of thing :(
java.lang.IllegalArgumentException: Cannot cast PERSO of type com.wimova.domain.model.Usage.PERSO to a NavType. Make sure to provide custom NavType for this argument.
@Serializable
data class NewReservationDetails(val usage: Usage) {
companion object {
val typeMap = mapOf(typeOf<Usage>() to NavType.EnumType<Usage>(Usage::class.java))
fun from(savedStateHandle: SavedStateHandle) =
savedStateHandle.toRoute<Usage>(typeMap)
}
}
composable<NewReservationDetails>(
enterTransition = { expandHorizontally() },
exitTransition = { shrinkHorizontally() },
typeMap = NewReservationDetails.typeMap
) { backStackEntry ->
val parentEntry = remember(backStackEntry) {
navController.getBackStackEntry(NewReservation)
}
val parentViewModel: OrderRideHostViewModel = hiltViewModel(parentEntry)
val viewModel: OrderRideAddressDateViewModel = hiltViewModel()
NewReservationDetailsScreen(
orderRideAddressDateViewModel = viewModel,
orderRideHostViewModel = parentViewModel
)
}
)
class OrderRideAddressDateViewModel @Inject constructor(
val savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val usage = NewReservationDetails.from(savedStateHandle)
}
I'm still having the crash, i've tried a lot of thing :(
java.lang.IllegalArgumentException: Cannot cast PERSO of type com.wimova.domain.model.Usage.PERSO to a NavType. Make sure to provide custom NavType for this argument.
il...@google.com <il...@google.com> #15
Re
na...@google.com <na...@google.com> #16
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-common:2.9.0-alpha01
Description
Component used: Navigation Version used: Version 2.8.0-beta07 Devices/Android versions reproduced on: Pixel 6Pro Android14 The release notes for Version 2.8.0-beta07 state that there is not need to explicitly provide a typeMap for Enum classes but the App crashes on startup but works as expected if the typeMap is provided or the enum class is nested inside the destination serializable data class.
this one works
but this one fails
If this is a bug in the library, we would appreciate if you could attach: