suspender método dentro do bloco runInTransaction
Eu tenho um erro de compilação usando o código abaixo:
As funções de suspensão podem ser chamadas apenas dentro do corpo da co-rotina
Alguém pode me explicar por quê? O que preciso fazer para que funcione (sem usar a @Transactionanotação)?
override suspend fun replaceAccounts(newAccounts: List<Account>) {
database.runInTransaction {
database.accountDao().deleteAllAccounts() // I have the error on this line
database.accountDao().insertAccounts(newAccounts) // Here too
}
}
@Dao
abstract class AccountDao : BaseDao<AccountEntity> {
@Query("DELETE FROM Account")
abstract suspend fun deleteAllAccounts()
}
Agradeço antecipadamente por sua ajuda
Respostas
Para suspendfunções, use em withTransactionvez derunInTransaction
IO-bound e outras operações de longa duração (como chamadas de banco de dados ou API) não podem ser executadas diretamente no thread principal (o que poderia fazer com que seu programa parasse de responder). As corrotinas são como threads leves que são executados de forma assíncrona dentro de uma thread.
Eu sugiro a leitura do guia de corrotinas em https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html
Para responder à sua pergunta, você precisa configurar um escopo de co-rotina e thread de despachante para que sua co-rotina seja executada. O mais simples é algo como:
GlobalScope.launch(Dispatchers.IO) {
replaceAccounts(newAccounts)
}
que executaria sua co-rotina no GlobalScope (o "ciclo de vida" da co-rotina está vinculado ao ciclo de vida de todo o aplicativo), no encadeamento IO (um encadeamento fora do encadeamento principal que lida com as tarefas IO).
EDIT Eu gosto da resposta de @ IR42. Para construir sobre isso, o uso de withTransaction, neste caso, permite que a Room manipule o encadeamento em que as operações do banco de dados são realizadas e ajuda a limitar a simultaneidade no banco de dados.
GlobalScope.launch(Dispatchers.Main) {
replaceAccounts(newAccounts)
}
override suspend fun replaceAccounts(newAccounts: List<Account>) {
database.withTransaction {
database.accountDao().deleteAllAccounts() // I have the error on this line
database.accountDao().insertAccounts(newAccounts) // Here too
}
}
Veja mais informações sobre este artigo por um dos próprios Room: https://medium.com/androiddevelopers/threading-models-in-coroutines-and-android-sqlite-api-6cab11f7eb90