簡體   English   中英

即使從外部 function 取消后,協程作業也會完成

[英]Coroutine job completing even after cancellation from external function

我有這個 function:

suspend fun functionCall(): Job {
      return MainScope().launch {
       var i = 0
       while(i < 3) {
         i++
         delay(3000)
         yield()
      }
     }
    cancel()
}

當單擊按鈕時,我從外部 function 調用:

MainScope().launch {
   if(functionCall().isActive) {
      functionCall().cancelAndJoin()
   }
}

這兩個函數都在存儲庫 class 中運行。 即使在上面的 if 語句被觸發之后,它仍然會遍歷整個 while 循環。 我在調試時注意到“i”也被重置為 0,這可能表明該作業被多次觸發,但它肯定只被觸發一次,所以我對正在發生的事情感到困惑。

我想要發生的是在那之后取消整個作業的 if 語句以及整個 function 返回並不再運行代碼。

我也嘗試過 while(ensureActive) 並且發生了同樣的事情。

我該怎么做呢?

由於這是 Android,因此您應該從lifecycleScope范圍啟動與 UI 相關的協程。 如果您的作業需要在屏幕旋轉中幸存下來,您應該從viewModelScope的 ViewModel 內部啟動它,並且它不能觸及任何 UI 元素。

如果您想在事件發生時取消特定的協程,您應該將該協程 Job 存儲在一個屬性中,以便您可以在其上調用cancel() 因此,例如 Activity 中的典型模式可能是:

private var fooJob: Job? = null

private fun fooSomething() {
    fooJob = lifecycleScope.launch {
        repeat(5) {
            delay(1000)
            Log.i("count", it.toString())
        }
    }
}

private fun cancelCurrentFoo() {
    fooJob?.cancel()
}

假設您有一個協程作業,您可以通過調用 ViewModel 的一個函數開始,但您希望 Activity/Fragment 能夠提前取消它。 然后公開一個返回協程 Job 的 function:

fun foo() = viewModelScope.launch {
    repeat(5) {
        delay(1000)
        Log.i("count", it.toString())
    }
}

Activity 可以調用此 function 並獲得一個 Job 實例作為回報,它可以隨時調用cancel()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM