Android coroutine scope lost if called from a non suspendable block-ThrowExceptions

Exception or error:

I’m trying to execute a suspendable function from a lambda expression:

fun executeAll() {
     // non-ui thread required for this task. Retain the jobId and clear it once the VM is destroyed
     jobId = launch(Dispatchers.IO) {
         try {
             // execute all queries in one transaction
             appDatabase.runInTransaction {
                 // !! THIS --> "Suspension functions can be called only with coroutine body"
                 runQueries()
             }
         }
         catch (e: Exception) {
         }
     }
 }

 private suspend fun runQueries() {
     userRepository.deleteAll()
     userRepository.insertAll(users)
 }

 override fun onCleared() {
     super.onCleared()
     jobId?.cancel()
 }

Executing the runQueries() gives me an error, because it’s not called from a coroutine body. But how can I fix this? I’m already calling a launch(Dispatchers.IO). Should I create a new coroutine job? What have I done is I wrapped inside a runBlocking block:

runBlocking {
   runQueries()
}

But I’ve read that I shouldn’t use runBlocking in production, because it was a mistake by the Kotlin team and it was too late to remove it.

How to solve:

You must change runInTransaction to withTransaction.

Leave a Reply

Your email address will not be published. Required fields are marked *