房间: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 }