Room LiveData 观察器 (onChange) 触发多次但仅针对 INSERT
Room LiveData observer (onChange) fired multiple times but only for INSERT
我注意到 android Room 图书馆有一些奇怪的行为(至少对我来说看起来很奇怪)。
虽然还有其他帖子有 类似 问题,但其中 none 个(我能找到)与此完全相同。
我的问题是,当我观察一个 LiveData
对象时,我的观察者的 onChange()
方法被多次调用,但仅用于 INSERT 操作。对于我插入的每个对象,该方法将被触发一次(即,如果我插入一个包含 N 个对象的列表,它将被触发 N 次),而对于其他操作(例如 DELETE),无论列表的大小如何,它都会被触发一次我正在删除。
我的 DAO 中有以下查询:
@query("select * from myTable")
LiveData<myEntity> getAll();
@insert
void insert(List<myEntity> entities);
@delete
void delete(List<myEntity> entities);
我正在观察 getAll()
方法,我肯定会调用 delete()
和 insert()
方法一次 - 像这样:
public void insertAll(List<myEntity> items)
{
myDao.insert(items);
}
和
public void deleteAll(List<myEntity> items)
{
myDao.delete(items);
}
因为在我的 onChange()
方法中我正在更新用户可见的 RecyclerView
适配器,这是一个问题,因为我得到了很多重复项,而且我还在做一些其他的事情那里的东西每次 table 更改时实际上只应该执行一次,但它们会执行多次(正如我所说的,每插入一个项目一次)。
我已阅读这篇文章并尝试实施技巧 7,但问题仍然存在。
https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1
这是设计使然并被认为是正常行为吗?我该怎么做才能让我的观察者对每个 INSERT 操作只触发一次(即使我同时插入多个对象)?
虽然我不完全理解它,但我找到了解决方案!
我的问题是我从 onNewIntent()
呼叫 observe()
,我的呼叫看起来像这样:
mViewModel.getAll().observe(this, new Observer<ArrayList<MyObject>>()...);
我从 onNewIntent()
调用这个的原因是这个 activity 几乎可以在我的应用程序的任何地方使用标志 BRING_TO_FRONT
(或任何它叫的)打开所以 onCreate()
不能保证被调用所以我想我最好通过将它放在 onNewIntent()
中来确保调用观察者。
我看了他们说的文档
If the given owner, observer tuple is already in the list, the call is
ignored.
所以我以为我很安全。由于某种原因我没有意识到的是,我实际上每次都使用 new
关键字创建一个新的观察者。从 onNewIntent()
调用它的组合导致多个 duplicate 观察者导致 onChanged()
方法被触发多次(实际上它只被调用一次, 但每个观察者一次!).
一旦我将 observe()
调用移至 onCreate()
,问题就解决了,即使我向 table 插入多个项目,我也会收到一个对 onChanged()
的调用.
然而,这仍然没有解释 delete
方法如何只被调用一次用于多个...
我注意到 android Room 图书馆有一些奇怪的行为(至少对我来说看起来很奇怪)。
虽然还有其他帖子有 类似 问题,但其中 none 个(我能找到)与此完全相同。
我的问题是,当我观察一个 LiveData
对象时,我的观察者的 onChange()
方法被多次调用,但仅用于 INSERT 操作。对于我插入的每个对象,该方法将被触发一次(即,如果我插入一个包含 N 个对象的列表,它将被触发 N 次),而对于其他操作(例如 DELETE),无论列表的大小如何,它都会被触发一次我正在删除。
我的 DAO 中有以下查询:
@query("select * from myTable")
LiveData<myEntity> getAll();
@insert
void insert(List<myEntity> entities);
@delete
void delete(List<myEntity> entities);
我正在观察 getAll()
方法,我肯定会调用 delete()
和 insert()
方法一次 - 像这样:
public void insertAll(List<myEntity> items)
{
myDao.insert(items);
}
和
public void deleteAll(List<myEntity> items)
{
myDao.delete(items);
}
因为在我的 onChange()
方法中我正在更新用户可见的 RecyclerView
适配器,这是一个问题,因为我得到了很多重复项,而且我还在做一些其他的事情那里的东西每次 table 更改时实际上只应该执行一次,但它们会执行多次(正如我所说的,每插入一个项目一次)。
我已阅读这篇文章并尝试实施技巧 7,但问题仍然存在。 https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1
这是设计使然并被认为是正常行为吗?我该怎么做才能让我的观察者对每个 INSERT 操作只触发一次(即使我同时插入多个对象)?
虽然我不完全理解它,但我找到了解决方案!
我的问题是我从 onNewIntent()
呼叫 observe()
,我的呼叫看起来像这样:
mViewModel.getAll().observe(this, new Observer<ArrayList<MyObject>>()...);
我从 onNewIntent()
调用这个的原因是这个 activity 几乎可以在我的应用程序的任何地方使用标志 BRING_TO_FRONT
(或任何它叫的)打开所以 onCreate()
不能保证被调用所以我想我最好通过将它放在 onNewIntent()
中来确保调用观察者。
我看了他们说的文档
If the given owner, observer tuple is already in the list, the call is ignored.
所以我以为我很安全。由于某种原因我没有意识到的是,我实际上每次都使用 new
关键字创建一个新的观察者。从 onNewIntent()
调用它的组合导致多个 duplicate 观察者导致 onChanged()
方法被触发多次(实际上它只被调用一次, 但每个观察者一次!).
一旦我将 observe()
调用移至 onCreate()
,问题就解决了,即使我向 table 插入多个项目,我也会收到一个对 onChanged()
的调用.
然而,这仍然没有解释 delete
方法如何只被调用一次用于多个...