I found that the LiveData returned by Dao will call its observer whenever the row is updated in DB, even if the LiveData value is obviously not changed.
Consider a s
Avoid false positive notifications for observable queries
Let’s say that you want to get a user based on the user id in an observable query:
@Query(“SELECT * FROM Users WHERE userId = :id)
fun getUserById(id: String): LiveData
You’ll get a new emission of the User
object whenever that user updates. But you will also get the same object when other changes (deletes, updates or inserts) occur on the Users
table that has nothing to do with the User
you’re interested in, resulting in false-positive notifications. Even more, if your query involves multiple tables, you’ll get a new emission whenever something changed in any of them.
If your query returns a LiveData, you can use a MediatorLiveData that only allows distinct object emissions from a source.
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
}
In your DAOs, make method that returns the distinct LiveData public and the method that queries the database protected.
@Dao
abstract class UserDao : BaseDao() {
@Query(“SELECT * FROM Users WHERE userid = :id”)
protected abstract fun getUserById(id: String): LiveData
fun getDistinctUserById(id: String):
LiveData = getUserById(id).getDistinct()
}
See more of the code here and also in Java.