我有一個問題......有時,我需要直接從 ViewModel 獲取資料。例如,假設isChecked()
ViewModel 中有一個方法。我想在 if 條件下使用它。
if(viewModel.isChecked()){
// TODO:
}
所以,我現在正在做的是:
fun isChecked(): Boolean = runBlocking {
val result = dbRepo.getData()
val response = apiRepo.check(result)
return response.isSuccessful
}
它使用 runBlocking。因此,它在 MainThread 上運行。我認為這不是一個好方法,因為它可以凍結螢屏。但是是的,如果條件需要運行,它需要等待它從資料庫和網路獲取資料。
我能想到的另一種方法是使用 LiveData。但是,我不能在這種情況下使用它。所以,我需要在觀察者塊中移動條件。但有時,這不能完成,因為條件之前可能有一些東西。它看起來并不直接,而是在這里和那里撰寫代碼并最終獲得該資料。
那么,還有比這更簡單的方法嗎?
uj5u.com熱心網友回復:
如果您遇到此類緩慢或阻塞的情況,最好的選擇是重新考慮您如何完全使用資料。不要嘗試回傳它,而是使用 LiveData 或回呼來異步處理回應,而不會導致 UI 掛起或變得滯后。在這些情況下,您實際上只有三個選擇:
- 收到回應時使用回呼處理
- 收到回應時使用 LiveData 等可觀察資料進行處理
- 將方法更改為掛起函式并從協程中呼叫它
強制方法等待回傳主執行緒而不使用其中之一將導致應用程式掛起。
回呼以獲取狀態
如果沒有關于如何使用的更多詳細資訊,很難確定最適合您的解決方案是什么isChecked()
,但一種可行的模式是使用回呼來處理您以前放入 if 陳述句中的內容,就像這樣(在視圖模型):
fun getCheckedState(callback: (Boolean)->Unit) {
viewModelScope.launch {
// do long-running task to get checked state,
// using an appropriate dispatcher if needed
val result = dbRepo.getData()
val response = apiRepo.check(result)
// pass "response.isSuccessful" to the callback, to be
// used as "isChecked" below
callback(response.isSuccessful)
}
}
您可以像這樣從活動或片段中呼叫它:
viewModel.getCheckedState { isChecked ->
if( isChecked ) {
// do something
}
else {
// do something else
}
}
// CAUTION: Do NOT try to use variables you set inside
// the callback out here!
請注意- 您傳遞給的回呼中的代碼getCheckedState
不會立即運行。不要嘗試在回呼范圍之外使用你在里面設定的東西,否則你會陷入這個常見問題
更簡單的回呼
或者,如果您只想在isChecked
為真時運行一些代碼,您可以像這樣簡化回呼
fun runIfChecked(callback: ()->Unit) {
viewModelScope.launch {
// do long-running task to get checked state,
// using an appropriate dispatcher if needed
val result = dbRepo.getData()
val response = apiRepo.check(result)
// only call the callback when it's true
if( response.isSuccessful ) {
callback()
}
}
}
并呼叫它
viewModel.runIfChecked {
// do something
}
// Again, don't try to use things from the callback out here!
uj5u.com熱心網友回復:
使用lifecyclescope.launch(Dispatcher.IO) 而不是runblocking
uj5u.com熱心網友回復:
在您的 ViewModel 類上嘗試以下代碼:
suspend fun isChecked(): Boolean {
val response: Response? = null
viewModelScope.launch(Dispatchers.IO) {
val result = dbRepo.getData()
response = apiRepo.check(result)
}.join()
return response?.isSuccessful
}
從活動:
// Suppose you have a button
findViewById<Button>(R.id.btn).setOnClickListener({
CoroutineScope(Dispatchers.Main).launch {
if (viewModel.isChecked()) {
Log.d("CT", "Do your others staff")
}
}
})
希望它作業檔案。如果沒有讓我評論
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/507360.html