Room 数据库中的事务返回 LiveData

Transaction in Room Database returning LiveData

我想从旧记录中删除一个 table,然后计算其中的记录数。

@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
}

不幸的是,这个查询 return 是一个错误

error: Method annotated with @Transaction must not return deferred/async return type androidx.lifecycle.LiveData. Since transactions are thread confined and Room cannot guarantee that all queries in the method implementation are performed on the same thread, only synchronous @Transaction implemented methods are allowed. If a transaction is started and a change of thread is done and waited upon then a database deadlock can occur if the additional thread attempts to perform a query. This restrictions prevents such situation from occurring.

现在,我想在一个事务中按顺序执行 -delete- 和 -select count- 操作序列,return 来自 -select 的 LiveData计数操作。这在我看来是合法的。 问题:

  1. 事务中的查询不是顺序执行的吗?
  2. 为什么会出错?
  3. 如果无法从交易中获取 LiveData,如何获得相同的行为,例如使用 MutableLiveDataInvalidationTracker.Observer#onInvalidated 通知?

第 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
}

使用@Transaction 注解时将LiveData 更改为MutableLiveData。 我知道已经很晚了。但是,仍然有一些人可以从中受益。