ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android – Room:来自Dao的LiveData会在每次更新时触发Observer.onChanged,即使LiveData值没有变化

2019-10-01 22:27:13  阅读:682  来源: 互联网

标签:android-room android android-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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有