Android - 用于处理 IllegalStateException 的 Kotlin 协程:无法访问主线程上的数据库

abd*_*lik 2 android illegalstateexception android-room kotlin-coroutines

在我的 Android 应用程序中,我使用Room本地数据库来存储用户的帐户信息。当我发出一个简单的Room请求来检索Account存储在数据库中的对象时,我收到以下错误消息:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
Run Code Online (Sandbox Code Playgroud)

这是Fragment我发出本地数据库请求的代码:

// AccountInformationFragment.kt


accountDataFragmentViewModel.retrieveAccountData(accountId).observe(viewLifecycleOwner, Observer {
       // do some stuff
    })
Run Code Online (Sandbox Code Playgroud)

ViewModel课堂上我是这样实现的retrieveAccountData()

    // AccountInformationFragmentViewModel.kt        

    // used to get the account from the local datasource
    fun retrieveAccountData(id:Long): LiveData<Account>{
        val result = MutableLiveData<Account>()
        viewModelScope.launch {
            val account = authRepository.retrieveAccountData(id)
            result.postValue(account) 
        }
        return result
    }
Run Code Online (Sandbox Code Playgroud)

Repository课堂上,我是这样实现的retrieveAccountData()

// AccountRepository.kt

suspend fun retrieveAccountData(accId:Long): Account =
        accountDao.retrieveAccountData(accId)
Run Code Online (Sandbox Code Playgroud)

我知道我必须使用某种 asnyc 操作,因为本地数据库操作在主线程上执行时可能需要很长时间。但是在ViewModel课堂上,我在viewModelScope. 这还不够吗?根据例外情况,似乎不是。那么,有没有人可以告诉我如何正确地做到这一点。

编辑:

这是 Dao 类:

@Query("SELECT * FROM account_table WHERE id = :id")
fun retrieveAccountData(id: Long) : Account
Run Code Online (Sandbox Code Playgroud)

提前致谢

ian*_*ake 6

根据Room 文档,如果您希望 Room 自动移动到后台线程来运行您的@Query,您可以将您的方法设为suspend方法:

@Query("SELECT * FROM account_table WHERE id = :id")
suspend fun retrieveAccountData(id: Long) : Account
Run Code Online (Sandbox Code Playgroud)