android – Room:来自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<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);
UI中的某个地方
// 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在室内设计的行为吗?我是否有机会解决这个问题,以便只在更新所选字段时才会调用观察者?
编辑:我更改为使用以下查询将lastActiveDateTime值更新为评论建议中的KuLdip PaTel.仍然会调用用户名LiveData的观察者.
@Query("UPDATE User set lastActiveDateTime = :lastActiveDateTime where id = :id")
void updateLastActiveDateTime(Date lastActiveDateTime, int id);
解决方法:
这种情况被称为观察者的误报通知.
请检查link中提到的第7点以避免此类问题.
Below example is written in kotlin but you can use its java version to get it work.
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
}
标签:android-room,android,android-livedata 来源: https://codeday.me/bug/20191001/1840335.html