runInTransaction 블록 내부의 suspend 메소드

Sep 01 2020

아래 코드를 사용하여 컴파일 오류가 있습니다.

서스펜션 함수는 코 루틴 본문 내에서만 호출 할 수 있습니다.

누군가 나에게 이유를 설명 할 수 있습니까? @Transaction주석 을 사용하지 않고 작동하려면 어떻게해야 합니까?

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

}

도움에 미리 감사드립니다.

답변

9 IR42 Sep 01 2020 at 02:58

에 대한 suspend기능을 사용 withTransaction하는 대신runInTransaction

hightech Sep 01 2020 at 03:02

IO 바인딩 및 기타 장기 실행 작업 (예 : 데이터베이스 또는 API 호출)은 기본 스레드에서 직접 실행되지 않도록 제한됩니다 (그렇지 않으면 프로그램이 응답하지 않을 수 있음). 코 루틴은 스레드 내에서 비동기 적으로 실행되는 경량 스레드와 같습니다.

나는 코 루틴 가이드를 읽는 것이 좋습니다. https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html

질문에 답하려면 코 루틴 범위와 코 루틴을 실행할 디스패처 스레드를 설정해야합니다. 가장 간단한 방법은 다음과 같습니다.

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

IO 스레드 (IO 작업을 처리하는 주 스레드 외부의 스레드)에서 GlobalScope (코 루틴의 "라이프 사이클"은 전체 애플리케이션의 라이프 사이클에 바인딩 됨)에서 코 루틴을 실행합니다.

편집 나는 @ IR42의 대답을 좋아합니다. 이를 기반 withTransaction으로이 경우를 사용하면 Room에서 데이터베이스 작업이 수행되는 스레드를 처리하고 데이터베이스에 대한 동시성을 제한하는 데 도움이됩니다.

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

이 문서에 대한 자세한 내용은 Room 자체에서 확인하세요. https://medium.com/androiddevelopers/threading-models-in-coroutines-and-android-sqlite-api-6cab11f7eb90