房间:Dao的LiveData将在每次更新时触发Observer.onChanged,即使LiveData值没有变化
我发现Dao返回的LiveData将在DB更新行时调用其观察者,即使LiveData值显然没有改变。
考虑下面的例子:
示例实体
@Entity public class User { public long id; public String name; // example for other variables public Date lastActiveDateTime; }
例如道
@Dao public interface UserDao { // I am only interested in the user name @Query("SELECT name From User") LiveData<List> getAllNamesOfUser(); @Update(onConflict = OnConflictStrategy.REPLACE) void updateUser(User user); }
在后台线程的某处
UserDao userDao = //.... getting the dao User user = // obtain from dao.... user.lastActiveDateTime = new Date(); // no change to user.name userDao.updateUser(user);
用户界面中的某处
// omitted ViewModel for simplicity userDao.getAllNamesOfUser().observe(this, new Observer<List> { @Override public void onChanged(@Nullable List userNames) { // this will be called whenever the background thread called updateUser. // If user.name is not changed, it will be called with userNames // with the same value again and again when lastActiveDateTime changed. } });
在这个例子中,ui只对用户名感兴趣,因此对LiveData的查询只包含名称字段。 但是,即使只有其他字段被更新,observer.onChanged仍然会在Dao Update上被调用。 (实际上,如果我没有对User实体进行任何更改并调用UserDao.updateUser,observer.onChanged仍将被调用)
这是在房间里Dao LiveData的设计行为吗? 是否有任何机会我可以解决这个问题,以便观察员将只在选定的字段更新时被调用?
编辑:我改为使用以下查询更新为评论建议KuLdip PaTel lastActiveDateTime值。 用户名LiveData的观察者仍然被调用。
@Query("UPDATE User set lastActiveDateTime = :lastActiveDateTime where id = :id") void updateDeviceLevel(long id, int level);
这种情况被称为观察员的误报通知。 请检查链接中提到的第7点以避免此类问题。
下面的例子是写在kotlin,但你可以使用它的Java版本来得到它的工作。
fun LiveData .getDistinct(): LiveData { val distinctLiveData = MediatorLiveData () distinctLiveData.addSource(this, object : Observer { private var initialized = false private var lastObj: T? = null override fun onChanged(obj: T?) { if (!initialized) { initialized = true lastObj = obj distinctLiveData.postValue(lastObj) } else if ((obj == null && lastObj != null) || obj != lastObj) { lastObj = obj distinctLiveData.postValue(lastObj) } } }) return distinctLiveData }