Fixed
Status Update
Comments
[Deleted User] <[Deleted User]> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
ka...@gmail.com <ka...@gmail.com> #3
yea i'll take it.
[Deleted User] <[Deleted User]> #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.
ca...@gmail.com <ca...@gmail.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()
}
}
il...@google.com <il...@google.com>
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} )
}
il...@google.com <il...@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-master-dev
commit 3cc9b77742508c095f3268b60956967bce46f0ed
Author: Ian Lake <ilake@google.com>
Date: Sat Mar 30 08:40:04 2019
Save and restore back stack UUIDs for getViewModelStore()
As each NavBackStackEntry has a UUID which matches
the non-config ViewModelStore for each graph, we
need to make sure that those UUIDs are properly
saved and restored across configuration changes to
ensure that when you ask for a particular
ViewModelStore, you get the same object back.
Test: new testSaveRestoreGetViewModelStore
BUG: 111614463
Change-Id: Ie174eeae7318e9b8ba233e58df57f960a8861d99
M navigation/common/src/main/java/androidx/navigation/NavBackStackEntry.java
M navigation/runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
https://android-review.googlesource.com/936699
https://goto.google.com/android-sha1/3cc9b77742508c095f3268b60956967bce46f0ed
Branch: androidx-master-dev
commit 3cc9b77742508c095f3268b60956967bce46f0ed
Author: Ian Lake <ilake@google.com>
Date: Sat Mar 30 08:40:04 2019
Save and restore back stack UUIDs for getViewModelStore()
As each NavBackStackEntry has a UUID which matches
the non-config ViewModelStore for each graph, we
need to make sure that those UUIDs are properly
saved and restored across configuration changes to
ensure that when you ask for a particular
ViewModelStore, you get the same object back.
Test: new testSaveRestoreGetViewModelStore
BUG: 111614463
Change-Id: Ie174eeae7318e9b8ba233e58df57f960a8861d99
M navigation/common/src/main/java/androidx/navigation/NavBackStackEntry.java
M navigation/runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
tu...@gmail.com <tu...@gmail.com> #10
unresolved reference: by navGraphViewModels(R.id...)?
[Deleted User] <[Deleted User]> #11
In that case what if I have a global navigation action screen let's say for this example a CountryPickerFragment where I want to share data between this screen and the parent caller fragment only (not the entire navigation graph) and I want it cleared after the parent is done how could I scope the ViewModel in that case?
[Deleted User] <[Deleted User]> #12
That is a different issue, that is not yet available. What you want is actually opening a screen while waiting for a result. Check:
https://issuetracker.google.com/issues/79672220
b9...@gmail.com <b9...@gmail.com> #13
What's the difference between graph scoped and parent Fragment/Activity scoped ViewModel?
Navigation graph use child fragment manager to navigate its graph, I think it equals to use parent Fragment scoped ViewModel.
Navigation graph use child fragment manager to navigate its graph, I think it equals to use parent Fragment scoped ViewModel.
ra...@gmail.com <ra...@gmail.com> #14
In reference to #8 how would this work when one needs to implement an app flow of "single activity wih multiple fragments" where also you could share a parent fragment viewmodel with it's child/nested fragments. Referring to your talk on Google IO/19 navGraphViewModels work with only the fragments within the same graph, so how does one share the parent fragment viewmodel with it's child fragment in such a case?
ma...@gmail.com <ma...@gmail.com> #15
In reference to #14... ¿When using dynamic feature modules, the navGraphViewModels property delegate work while the destination are in the same nav graph, how do i handle the scenario when the destinations are included dynamically and separated in their respective DFM ?
Description
Version used: 1.0.0-alpha03
When using nested graph or included graphs to represent certain flows (such as user sign up or checkout), it would be nice to have a built in way to share data across all of these destinations while ensuring that it is cleaned up after the entire graph is removed from the back stack.
Effectively a ViewModel that has a scope somewhere between a single Fragment / ViewModelStoreOwner destination and an Activity scoped ViewModel.