Транзакция в базе данных комнат, возвращающая LiveData - PullRequest
0 голосов
/ 12 марта 2020

Я хотел бы удалить таблицу из старых записей, а затем сосчитать записи в ней.

@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, не должен возвращать отложенный / асин c тип возврата androidx.lifecycle.LiveData. Поскольку транзакции ограничены потоками, и Room не может гарантировать, что все запросы в реализации метода выполняются в одном потоке, разрешены только синхронные методы, реализованные в @Transaction. Если транзакция запущена, а изменение потока выполнено и ожидается, тогда может произойти взаимоблокировка базы данных, если дополнительный поток попытается выполнить запрос. Эти ограничения предотвращают возникновение такой ситуации.

Теперь я хотел бы выполнить последовательность операций -delete- и -select-последовательно и за одну транзакцию и вернуть LiveData из -select счетная операция. Это кажется мне законным. Вопросы:

  1. Разве запросы внутри транзакции не выполняются последовательно?
  2. Почему возникает ошибка?
  3. Как получить такое же поведение, например, с помощью MutableLiveData и InvalidationTracker.Observer#onInvalidated уведомление, если невозможно получить LiveData из транзакций?

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Измените LiveData на MutableLiveData при использовании аннотации @Transaction. Я знаю, что уже очень поздно. Но все же некоторые люди могут извлечь из этого пользу.

0 голосов
/ 18 марта 2020

Пункты 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...