【问题标题】: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。这在我看来是合法的。 问题:

  1. 事务中的查询不是按顺序执行的吗?
  2. 为什么会出错?
  3. 如果无法从交易中获取 LiveData,如何获得相同的行为,例如使用MutableLiveDataInvalidationTracker.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。 我知道已经很晚了。但是,仍然有一些人可以从中受益。

      【讨论】:

      • 为什么?您认为这应该会产生什么影响?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 2018-08-27
      • 2018-07-07
      相关资源
      最近更新 更多