Fixed
Status Update
Comments
lo...@gmail.com <lo...@gmail.com> #2
Comment has been deleted.
il...@google.com <il...@google.com>
cl...@google.com <cl...@google.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.
ap...@google.com <ap...@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()
}
}
ap...@google.com <ap...@google.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)
ap...@google.com <ap...@google.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} )
}
ap...@google.com <ap...@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
ap...@google.com <ap...@google.com> #9
Project: platform/frameworks/support
Branch: androidx-main
commit 3323f0d63b410dc7c3e68c7377f520a063e23043
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 16:46:08 2023
Add clearBackStack support for exact routes
NavController.clearBackStack(route) now supports routes with arguments partially or fully filled in, as long as the route is exact match with route used to popBackStack(route).
This method defaults to original behavior of route matching through route pattern. If that fails, it recognizes the provided route as having arguments filled in and will attempt to match with exact arguments.
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 257514373
Relnote: "NavController.clearBackStack(route) now supports routes with arguments partially or fully filled in. Note that the arguments has to be an exact match with the route used to popBackStack(route)."
Change-Id: Ic678cf67db0f47f7b2778b039242773767735f2c
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
https://android-review.googlesource.com/2396202
Branch: androidx-main
commit 3323f0d63b410dc7c3e68c7377f520a063e23043
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 16:46:08 2023
Add clearBackStack support for exact routes
NavController.clearBackStack(route) now supports routes with arguments partially or fully filled in, as long as the route is exact match with route used to popBackStack(route).
This method defaults to original behavior of route matching through route pattern. If that fails, it recognizes the provided route as having arguments filled in and will attempt to match with exact arguments.
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 257514373
Relnote: "NavController.clearBackStack(route) now supports routes with arguments partially or fully filled in. Note that the arguments has to be an exact match with the route used to popBackStack(route)."
Change-Id: Ic678cf67db0f47f7b2778b039242773767735f2c
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #10
Project: platform/frameworks/support
Branch: androidx-main
commit 6609c2dbffca40ed6ae2742efe153409d07c4ae3
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 10:56:04 2023
Refactor helper functions in Navigation
Refactored helper functions NavController.restoreStateInternal and NavDeeplink.hasRoute
Test: n/a
Bug: 257514373
Change-Id: I30e28856b20c1a61a4cb2e6754a675803f81b3c5
M navigation/navigation-common/src/main/java/androidx/navigation/NavDestination.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
https://android-review.googlesource.com/2396201
Branch: androidx-main
commit 6609c2dbffca40ed6ae2742efe153409d07c4ae3
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 10:56:04 2023
Refactor helper functions in Navigation
Refactored helper functions NavController.restoreStateInternal and NavDeeplink.hasRoute
Test: n/a
Bug: 257514373
Change-Id: I30e28856b20c1a61a4cb2e6754a675803f81b3c5
M navigation/navigation-common/src/main/java/androidx/navigation/NavDestination.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
ap...@google.com <ap...@google.com> #11
Project: platform/frameworks/support
Branch: androidx-main
commit 8bac1f9b2b66fbd29277b14bb16cc586c05969ac
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 10:46:44 2023
Updated findDestination and findNode for routes
NavController.findDestination(route) and NavGraph.findNode(route) maintains original behavior of first finding based on route converted to destinationId. But if that fails, it will search based on NavDestination.matchDeepLink.
Refactored existing test toStringStartDestInNodesRouteWithID because it now properly matches with the startDestination.
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 257514373
Change-Id: I2d1c78d459ac3efce485f0b1113cac3348e0cde9
M navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
https://android-review.googlesource.com/2396200
Branch: androidx-main
commit 8bac1f9b2b66fbd29277b14bb16cc586c05969ac
Author: Clara Fok <clarafok@google.com>
Date: Thu Jan 19 10:46:44 2023
Updated findDestination and findNode for routes
NavController.findDestination(route) and NavGraph.findNode(route) maintains original behavior of first finding based on route converted to destinationId. But if that fails, it will search based on NavDestination.matchDeepLink.
Refactored existing test toStringStartDestInNodesRouteWithID because it now properly matches with the startDestination.
Test: ./gradlew navigation:navigation-runtime:cC
Bug: 257514373
Change-Id: I2d1c78d459ac3efce485f0b1113cac3348e0cde9
M navigation/navigation-common/src/androidTest/java/androidx/navigation/NavGraphAndroidTest.kt
M navigation/navigation-common/src/main/java/androidx/navigation/NavGraph.kt
M navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerRouteTest.kt
M navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
cl...@google.com <cl...@google.com> #12
This has been fixed internally and will be available in navigation 2.6.0-alpha05
pr...@google.com <pr...@google.com> #13
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.navigation:navigation-common:2.6.0-alpha05
androidx.navigation:navigation-runtime:2.6.0-alpha05
hu...@lunabee.com <hu...@lunabee.com> #14
Hi, If we have a NavHost like this:
val route = "home?opt={argOpt}"
NavHost(navController = navController, startDestination = route) {
composable(
route = route,
arguments = listOf(
navArgument("opt") {
type = NavType.StringType
nullable = true
defaultValue = null
},
),
)
}
The following methods don't work:
navController.getBackStackEntry("home") // or "home?" or "home?opt=" <- Lead to crash
navController.popBackStack("home", false) } // or "home?" or "home?opt=" <- ignore navigation
However, if we put a default value different than null
, it's working.
Is it possible to popback
to a destination with a default value set to null
?
il...@google.com <il...@google.com> #15
Re "home"
and "home?opt=null"
should work.
Description
Currently, the Navigation APIs that take routes actually use something that is more like a route pattern without any specific arguments that could be used to differentiate the routes. So when you call
getBackStackEntry(route)
orpopBackStack(route)
navigation cannot differentiate between two destinations that may have the same route pattern, but with different arguments.We could add other APIs that take a route pattern instead that maintains the old behavior and change the current APIs to consider the exact route. This would allow Navigation to differentiate between destinations with the same route pattern and different arguments.