我发现Dao返回的LiveData会在数据库中更新该行时立即调用其观察者,即使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<String>> 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<String>> {
    @Override
    public void onChanged(@Nullable List<String> 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的查询仅包括名称字段。但是,即使仅更新其他字段,仍然会在Dao Update上调用observer.onChanged。
(实际上,如果我不对User实体进行任何更改并调用UserDao.updateUser,仍将调用observer.onChanged)

这是Dao LiveData在Room中的设计行为吗?我是否有可能解决此问题,以便仅在更新选定字段时才调用观察者?

编辑:我更改为使用以下查询来更新lastActiveDateTime值,如注释建议中的KuLdip PaTel。用户名LiveData的观察者仍然被调用。
@Query("UPDATE User set lastActiveDateTime = :lastActiveDateTime where id = :id")
void updateLastActiveDateTime(Date lastActiveDateTime, int id);

最佳答案

这种情况称为观察者的误报。
请检查link中提到的第7点,以避免此类问题。


fun <T> LiveData<T>.getDistinct(): LiveData<T> {
    val distinctLiveData = MediatorLiveData<T>()
    distinctLiveData.addSource(this, object : Observer<T> {
        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
}

10-07 19:32
查看更多