Reputation: 619
I have noticed some strange behavior from the android Room library (at least it looks strange to me).
While there are other posts with similar problems, none of them (that I could find) are quite the same as this.
My issue is that when I observe a LiveData
object, my observers' onChange()
method is called multiple times but only for INSERT operation. The method will be triggered once for every object I insert (i.e. if I insert a list of N objects, it will be triggered N times), whereas for other operations (such as DELETE) it is fired once no matter the size of the list I am deleting.
I have the following queries in my DAO:
@query("select * from myTable")
LiveData<myEntity> getAll();
@insert
void insert(List<myEntity> entities);
@delete
void delete(List<myEntity> entities);
I am observing the getAll()
method and I am definitely calling the delete()
and insert()
methods one time - something like this:
public void insertAll(List<myEntity> items)
{
myDao.insert(items);
}
and
public void deleteAll(List<myEntity> items)
{
myDao.delete(items);
}
Since in my onChange()
method I am updating a RecyclerView
adapter which is visible to the user, this is a problem as I am getting a lot of duplicates and also I am doing some other things in there which should really only be done once every time the table changes but instead they are executed many times (as I've said, once for every item inserted).
I have read this article and tried to implement tip number 7 but the problem persists. https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1
Is this by design and considered normal behavior? What can I do to have my observer only fire once for every INSERT operation (even if I insert multiple objects at the same time)?
Upvotes: 1
Views: 2894
Reputation: 619
while i don't fully understand it, i found the solution!
my problem was that i was calling observe()
from onNewIntent()
and that my call looks like this:
mViewModel.getAll().observe(this, new Observer<ArrayList<MyObject>>()...);
the reason i was calling this from onNewIntent()
is that this activity can be opened from almost anywhere in my app using the flag BRING_TO_FRONT
(or whatever it's called) so onCreate()
is not guaranteed to be called so i figured i better make sure that the observer is called by putting it in onNewIntent()
.
i looked at the docs they say
If the given owner, observer tuple is already in the list, the call is ignored.
so i thought i was safe. what i failed to realize for some reason is that i am in fact creating a new observer every time with the new
keyword. that with the combination of calling it from onNewIntent()
lead to multiple duplicate observers which caused the onChanged()
method to be triggered multiple times (well actually it was only called once, but once per observer!).
once i moved the observe()
call to onCreate()
the problem was fixed and i get a single call to onChanged()
even when i insert multiple items to my table.
however this still does not explain how the delete
method was only called once for multiple...
Upvotes: 2