Android - 用于处理 IllegalStateException 的 Kotlin 协程:无法在主线程上访问数据库
Android - Kotlin Coroutines for handling IllegalStateException: Cannot access database on the main thread
在我的 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.
这里是我发出本地数据库请求的 Fragment
代码:
// AccountInformationFragment.kt
accountDataFragmentViewModel.retrieveAccountData(accountId).observe(viewLifecycleOwner, Observer {
// do some stuff
})
在 ViewModel
class 我已经实现了 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
}
在 Repository
class 中,我实现了 retrieveAccountData()
这样的:
// AccountRepository.kt
suspend fun retrieveAccountData(accId:Long): Account =
accountDao.retrieveAccountData(accId)
我知道我必须使用某种 asnyc 操作,因为本地数据库操作在主线程上执行时可能需要很长时间。
但是在 ViewModel
class 中,我在 viewModelScope
中启动了协程。这还不够吗?基于异常,似乎不是。那么,有没有人可以告诉我如何正确地做到这一点。
编辑:
这里是道 class :
@Query("SELECT * FROM account_table WHERE id = :id")
fun retrieveAccountData(id: Long) : Account
提前致谢
根据 Room documentation,如果您希望 Room 自动移动到 运行 您的 @Query
的后台线程,您可以将您的方法设为 suspend
方法:
@Query("SELECT * FROM account_table WHERE id = :id")
suspend fun retrieveAccountData(id: Long) : Account
RoomDB 支持 LiveData。您可以 return 查询结果作为实时数据,默认情况下它在后台线程中执行操作并在 UI 层中观察它。我已经在下面修改了您的查询,它将 return LiveData 而不是 Account。
@Query("SELECT * FROM account_table WHERE id = :id")
fun retrieveAccountData(id: Long) : LiveData<Account>
在我的 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.
这里是我发出本地数据库请求的 Fragment
代码:
// AccountInformationFragment.kt
accountDataFragmentViewModel.retrieveAccountData(accountId).observe(viewLifecycleOwner, Observer {
// do some stuff
})
在 ViewModel
class 我已经实现了 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
}
在 Repository
class 中,我实现了 retrieveAccountData()
这样的:
// AccountRepository.kt
suspend fun retrieveAccountData(accId:Long): Account =
accountDao.retrieveAccountData(accId)
我知道我必须使用某种 asnyc 操作,因为本地数据库操作在主线程上执行时可能需要很长时间。
但是在 ViewModel
class 中,我在 viewModelScope
中启动了协程。这还不够吗?基于异常,似乎不是。那么,有没有人可以告诉我如何正确地做到这一点。
编辑:
这里是道 class :
@Query("SELECT * FROM account_table WHERE id = :id")
fun retrieveAccountData(id: Long) : Account
提前致谢
根据 Room documentation,如果您希望 Room 自动移动到 运行 您的 @Query
的后台线程,您可以将您的方法设为 suspend
方法:
@Query("SELECT * FROM account_table WHERE id = :id")
suspend fun retrieveAccountData(id: Long) : Account
RoomDB 支持 LiveData。您可以 return 查询结果作为实时数据,默认情况下它在后台线程中执行操作并在 UI 层中观察它。我已经在下面修改了您的查询,它将 return LiveData 而不是 Account。
@Query("SELECT * FROM account_table WHERE id = :id")
fun retrieveAccountData(id: Long) : LiveData<Account>