Fixed
Status Update
Comments
du...@google.com <du...@google.com> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
ti...@chainels.com <ti...@chainels.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.
du...@google.com <du...@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()
}
}
du...@google.com <du...@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} )
}
Description
Component used: Paging
Version used: 3.0 alpha-04
Devices/Android versions reproduced on: n/a
Today (after many hours of debugging) I seem to have found a bug in latest alpha version of the Paging library. In my app I still have various lists that are not yet migrated to the new v3 API's, but since the documentation states it's backward compatible I figured that was okay.
Those lists use the database + remote pattern. One such list displayed strange behavior, it seemed to call all the boundary callbacks correctly, do the API call, and insert the new items in the database, however the items in the RecyclerView did not change.
The only difference that I could find between that list and other lists that were functioning correctly, is that it used a
map
function on theDatasource.Factory
returned by RoomI think I found the underlying issue. The data source does not seem to be invalidated when using a map function.
DataSource
has two variants ofaddOnValidationCallback
. An open functionThe Kotlin version is actually called in
LegacyPagingSource
However when using a map/mapByPage function on the factory returned by room, the source is wrapped and in that class ( , but also
WrappedDataSource
WrapperPositionalDataSource
for example) only the non Kotlin version ofaddOnValidationCallback
is overridden, and thus if called with the Kotlin version,addOnValidationCallback
is never called on the source of the wrapper.I could see when debugging that indeed
onInvalidatedCallbacks
is empty.Hopefully this is actually the cause of the behavior I'm seeing. The Paging code is quite complex so I could be missing something else.