Suspend-Methode im runInTransaction-Block

Sep 01 2020

Ich habe einen Kompilierungsfehler mit dem folgenden Code:

Aufhängungsfunktionen können nur innerhalb des Coroutine-Körpers aufgerufen werden

Kann mir jemand erklären warum? Was muss ich tun, damit es funktioniert (ohne die @TransactionAnmerkung zu verwenden)?

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()

}

Vielen Dank im Voraus für Ihre Hilfe

Antworten

9 IR42 Sep 01 2020 at 02:58

Für suspendFunktionen verwenden Sie withTransactionanstelle vonrunInTransaction

hightech Sep 01 2020 at 03:02

E / A-gebundene und andere lang laufende Vorgänge (wie Datenbank- oder API-Aufrufe) können nicht direkt im Hauptthread ausgeführt werden (was andernfalls dazu führen kann, dass Ihr Programm nicht mehr reagiert). Coroutinen sind wie leichte Threads, die asynchron innerhalb eines Threads ausgeführt werden.

Ich schlage vor, den Coroutines-Leitfaden unter zu lesen https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html

Um Ihre Frage zu beantworten, müssen Sie einen Coroutine-Bereich und einen Dispatcher-Thread einrichten, auf dem Ihre Coroutine ausgeführt werden kann. Das einfachste ist so etwas wie:

GlobalScope.launch(Dispatchers.IO) {
    replaceAccounts(newAccounts)
}

Dadurch wird Ihre Coroutine im GlobalScope (der "Lebenszyklus" der Coroutine ist an den Lebenszyklus der gesamten Anwendung gebunden) auf dem E / A-Thread (einem Thread außerhalb des Hauptthreads, der E / A-Aufgaben verarbeitet) ausgeführt.

BEARBEITEN Ich mag die Antwort von @ IR42. Um darauf aufzubauen, ermöglicht die Verwendung von withTransactionin diesem Fall Room, den Thread zu verarbeiten, in dem die Datenbankoperationen ausgeführt werden, und hilft, die Parallelität zur Datenbank zu begrenzen.

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
    }
}

Weitere Informationen zu diesem Artikel finden Sie bei einem von Room: https://medium.com/androiddevelopers/threading-models-in-coroutines-and-android-sqlite-api-6cab11f7eb90