Fixed
Status Update
Comments
se...@google.com <se...@google.com> #2
That seems quite bad :/ weird.
We have fairly large test projects which do not take anywhere close to it, maybe your code is triggering some bad code path.
Can you provide a sample or share your project with us? It is impossible to do something here unless we have a reproduction case. Might also possibly be related to your machine configuration.
We have fairly large test projects which do not take anywhere close to it, maybe your code is triggering some bad code path.
Can you provide a sample or share your project with us? It is impossible to do something here unless we have a reproduction case. Might also possibly be related to your machine configuration.
yb...@google.com <yb...@google.com> #3
Let me see what I can do on the reproduction as I am anyways blocked on this. I will try to extract out the DB module in a new project and see if it reproduces the issue.
yb...@google.com <yb...@google.com> #4
Attaching the sample project. When I run the project through the android studio or even command line, I see the described issue.
Try uncommenting room-compiler dependency from app's build.gradle, it does not have the issue because room compiler is not at work.
Try uncommenting room-compiler dependency from app's build.gradle, it does not have the issue because room compiler is not at work.
yb...@google.com <yb...@google.com> #5
Did you get a chance to look at it?
da...@gmail.com <da...@gmail.com> #6
FYI. I see that if I comment out applying google-services plugin (at the end of the app's build.gradle file), that fixes the issue too. Hence, you may need to apply a google-services plugin with a json file to reproduce the issue.
Not sure what is going on but certainly, somethings are not playing well together.
Not sure what is going on but certainly, somethings are not playing well together.
yb...@google.com <yb...@google.com> #7
Above comment is NOT TRUE, it seems I did not do a code change after commenting out apply google-services plugin. That's why the build passed.
ap...@google.com <ap...@google.com> #8
Thanks for the sample app. I haven't gotten to the bottom of the issue yet but I wanted to give you an update and it does seem indeed that Room is taking a very long time to parse and understand your queries via the ANTLR generated parser that Room uses. I'm not sure what is so special about your queries that is causing this, but I'll comment back with an update once I find out. Sadly for now I don't have a recommendation on a workaround.
Description
Version used: 2.2.0-alpha01
Devices/Android versions reproduced on: Android 9
I'm having some random crashes due to CoroutineLiveData
```
Fatal Exception: java.lang.IllegalArgumentException: This source was already added with the different observer
at androidx.lifecycle.MediatorLiveData.addSource + 89(MediatorLiveData.java:89)
at androidx.lifecycle.CoroutineLiveDataKt.addDisposableSource + 102(CoroutineLiveDataKt.java:102)
at androidx.lifecycle.CoroutineLiveData.emitSource$lifecycle_livedata_ktx_release + 200(CoroutineLiveData.java:200)
at androidx.lifecycle.LiveDataScopeImpl$emitSource$2.invokeSuspend + 89(LiveDataScopeImpl.java:89)
at androidx.lifecycle.LiveDataScopeImpl$emitSource$2.invoke(LiveDataScopeImpl.java:11)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn + 91(UndispatchedKt.java:91)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext + 156(BuildersKt__Builders_commonKt.java:156)
at kotlinx.coroutines.BuildersKt.withContext + 1(BuildersKt.java:1)
at androidx.lifecycle.LiveDataScopeImpl.emitSource + 88(LiveDataScopeImpl.java:88)
at com.geekorum.ttrss.articles_list.FeedsViewModel$refreshed$1.invokeSuspend + 90(FeedsViewModel.java:90)
at com.geekorum.ttrss.articles_list.FeedsViewModel$refreshed$1.invoke(FeedsViewModel.java:8)
at androidx.lifecycle.BlockRunner$maybeRun$1.invokeSuspend + 147(BlockRunner.java:147)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith + 33(BaseContinuationImpl.java:33)
at kotlinx.coroutines.DispatchedTask.run + 241(DispatchedTask.java:241)
at android.os.Handler.handleCallback + 873(Handler.java:873)
at android.os.Handler.dispatchMessage + 99(Handler.java:99)
at android.os.Looper.loop + 193(Looper.java:193)
at android.app.ActivityThread.main + 6898(ActivityThread.java:6898)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 537(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main + 858(ZygoteInit.java:858)
```
From what I understand of CoroutineLiveData source code, when calling `LiveDataScope.emitSource()` the previous source is removed before adding the new one on MediatorLiveData.
```
@MainThread
internal fun emitSource(source: LiveData<T>): DisposableHandle {
clearSource()
val newSource = addDisposableSource(source)
emittedSource = newSource
return newSource
}
```
However the removing is done by launching a new coroutine
```
internal fun <T> MediatorLiveData<T>.addDisposableSource(
source: LiveData<T>
): DisposableHandle {
val disposed = AtomicBoolean(false)
addSource(source) {
if (!disposed.get()) {
value = it
} else {
removeSource(source)
}
}
return object : DisposableHandle {
override fun dispose() {
if (disposed.compareAndSet(false, true)) {
CoroutineScope(Dispatchers.Main).launch {
removeSource(source)
}
}
}
}
}
```
So there is no guarantee that `MediatorLiveData.addSource()` will be called after the removing coroutine is executed. This leads to the IllegalArgumentException in `MediatorLiveData.addSource()`
```
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
```