最初,我直接訪問了一個 viewModel 函式,它為我正在運行的查詢啟動了一個 viewModel 范圍協程。那有同樣的錯誤。
然后,我將 viewModel 函式更改為掛起函式,并從片段中的協程呼叫它。那也沒有用。
所以,我這樣做是在一個協程中呼叫該函式,然后在 viewModel 范圍內運行另一個協程。這給出了相同的結果。
我認為在片段創建期間呼叫它可能會造成太多負載。所以我嘗試使用按鈕 onclick 偵聽器呼叫 viewModel 函式。再次墜毀。
我在資料庫檢查器中運行了相同的查詢,它運行良好。所以,查詢也不是問題。
在下面的螢屏截圖中,我包含了有關該問題的所有必要細節。只關注突出顯示的內容。從傳遞串列片段(左上選項卡)開始。從那里,呼叫右上角選項卡中的 viewModel 函式。從那里到它下面的 DAO。然后是它下面的資料類。
安卓作業室截圖——

viewModel 函式 -
fun resetAllAccess(){
viewModelScope.launch {
passwordDao.resetAccessForAll()
}
}
DAO 功能 -
@Query("UPDATE password_data SET access = 0 WHERE access = 1")
fun resetAccessForAll()
資料庫的資料類 -
@Entity(tableName = "password_data")
data class PasswordData(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
@ColumnInfo(name = "service_name") var serviceName: String,
@ColumnInfo(name = "service_password") var servicePassword: String,
@ColumnInfo(name = "is_an_application") var isAnApplication: Boolean = false,
@ColumnInfo(name = "use_finger_print") var useFingerPrint: Boolean = true,
@ColumnInfo(name = "access") var access: Boolean = false
)
來自片段的呼叫 -
CoroutineScope(Dispatchers.IO).launch { viewModel.resetAllAccess() }
uj5u.com熱心網友回復:
這是因為您正在使用viewModelScope. 很多人不知道這一點,但viewModelScope實際上是硬編碼以使用主執行緒而不是另一個執行緒。
您可以在Google 官方檔案中找到此資訊:
注意:ViewModel 類的 viewModelScope 屬性被硬編碼到 Dispatchers.Main。在測驗中使用 Dispatchers.setMain 和 TestCoroutineDispatcher 替換它,如 Android 中的簡易協程:viewModelScope 博客文章中所述。
因此,您可能希望將協程范圍傳遞給視圖模型類建構式(首選方式)或直接在視圖模型中創建一個。然后你應該使用它來啟動協程。
另一種常用的做法是創建一個同時包含視圖模型和自定義范圍(通過視圖模型建構式傳遞)的范圍。
例如:
class ViewModelClass(customCoroutineScope: CoroutineScope): ViewModel {
private val backgroundScope: CoroutineContext = customCoroutineScope.coroutineContext viewModelScope.coroutineContext
fun resetAllAccess(){
backgroundScope.launch {
passwordDao.resetAccessForAll()
}
}
}
您還可以在此處找到有關幕后viewModelScope作業原理的更多資訊。
還有另一種選擇,但我根本不推薦這樣做,原因很明顯,即通過使用Room 構建器中的allowMainThreadQueries允許 Room 在主執行緒中運行查詢。
uj5u.com熱心網友回復:
我替換了這個功能 -
fun resetAllAccess(){
viewModelScope.launch {
passwordDao.resetAccessForAll()
}
}
-和
fun resetAllAccess(){
CoroutineScope(Dispatchers.IO).launch {
passwordDao.resetAccessForAll()
}
}
所以現在,它不再在主執行緒上運行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/402912.html
標籤:
