【问题标题】:Transaction in Room Database returning LiveData房间数据库中的事务返回 LiveData
【发布时间】:2020-06-24 19:02:24
【问题描述】:
我想从旧记录中删除一个表,然后计算其中的记录。
@Transaction
private fun getOrdersCount(): LiveData<Int>
{
val now = LocalDateTime.now()
val firstOfMonth = now.withDayOfMonth(1)
subop_pruning(firstOfMonth) // query that deletes older orders
return subop_select_count() // query that returns the number of orders
}
不幸的是,这个查询返回一个错误
错误:使用 @Transaction 注释的方法不得返回延迟/异步返回类型 androidx.lifecycle.LiveData。由于事务是线程受限的,Room 不能保证方法实现中的所有查询都在同一个线程上执行,因此只允许同步 @Transaction 实现的方法。如果启动事务并且完成并等待线程更改,则如果附加线程尝试执行查询,则可能发生数据库死锁。此限制可防止此类情况发生。
现在,我想在一个事务中按顺序执行 -delete- 和 -select count- 操作序列,并从 -select count- 操作返回 LiveData。这在我看来是合法的。
问题:
- 事务中的查询不是按顺序执行的吗?
- 为什么会出错?
- 如果无法从交易中获取 LiveData,如何获得相同的行为,例如使用
MutableLiveData 和InvalidationTracker.Observer#onInvalidated 通知?
【问题讨论】:
标签:
android
transactions
android-sqlite
android-room
【解决方案1】:
第 1 点和第 2 点仍未得到解答,无论如何我是如何绕过问题的(根据第 3 点)。希望它可以帮助某人:
fun getOrderCount(): LiveData<Int> = object : LiveData<Int>(0) {
val observer = object : InvalidationTracker.Observer("order_table") {
override fun onInvalidated(tables: MutableSet<String>) {
requestOrderCount()
}
}
override fun onActive() {
super.onActive()
val tracker =
MyRoomDatabase.getInstance(applicationContext).invalidationTracker;
tracker.addObserver(observer)
requestOrderCount()
}
override fun onInactive() {
super.onInactive()
val tracker =
MyRoomDatabase.getInstance(applicationContext).invalidationTracker;
tracker.removeObserver(observer)
}
private fun requestOrderCount() {
// better to use coroutines than executors
Executors.newSingleThreadExecutor().execute {
postValue(
MyRoomDatabase.getInstance(applicationContext).OrderDao()
.getOrderCount_()
)
}
}
}
@Transaction
private fun getOrdersCount_(): LiveData<Int>
{
val now = LocalDateTime.now()
val firstOfMonth = now.withDayOfMonth(1)
subop_pruning(firstOfMonth) // query that deletes older orders
return subop_select_count() // query that returns the number of orders
}
【解决方案2】:
使用@Transaction 注解时将 LiveData 更改为 MutableLiveData。
我知道已经很晚了。但是,仍然有一些人可以从中受益。