I'd like to prune a table from old records and then count the records in it.
@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
}
unfortunately this query returns an error
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.
Now, i'd like to do the sequence of operations -delete- and -select count- sequentially and in one transaction and return the LiveData from the -select count- operation. This seems to me legitimate. Questions:
MutableLiveData
and InvalidationTracker.Observer#onInvalidated
notification if it's not possible to get LiveData from transactions?Point 1 and 2 remain unanswered, anyway here how i bypassed the problem (as per point 3). Hope it helps someone:
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
}