簡體   English   中英

返回屏幕時在 ViewModel 中取消協程

[英]Coroutine cancelled in ViewModel when coming back to screen

我的視圖中有以下代碼 model。

    viewModelScope.launch {
        val response = request.invoke(coroutineScope)
        responseBlock?.invoke(response)
    }.apply {
        invokeOnCompletion {
            Log.e("Cancellation", "2---", it)
            if (showLoading) {
                loadingCount--
                changeLoadingIfNeeded()
            }
        }
    }

我正在使用 jetpack navigator,它在第一次創建屏幕時運行良好,但是當我 go 到另一個屏幕並返回到這個屏幕時,協程被取消並顯示以下消息kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelled}@545aaed kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelled}@545aaed 為什么會發生這種情況,我該如何避免?

如果您不希望在 Fragment 或 Activity 被銷毀時取消協程,則必須將它們從 Fragment、Activity 或 ViewModel 的生命周期中解開。 對於這種情況,您可以創建一個新的協程 scope 來啟動; 例如:

CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
    val response = request.invoke(coroutineScope)
    responseBlock?.invoke(response)
}

如果你想在協程中進行 UI 操作,有一個快捷方式 function,它與上面的相同,唯一的區別是使用Dispatchers.Main啟動:

MainScope().launch {
    val response = request.invoke(coroutineScope)
    responseBlock?.invoke(response)
}

請記住,如果您不夠小心,您將遇到其他問題。 由於你的協程用完了一個生命周期,如果你在做UI操作,你需要手動檢查以下內容:

  1. 您嘗試更改的視圖是否仍然存在?
  2. 片段還存在嗎?
  3. 活動還存在嗎?

盡量不要在協程中保留對 Fragment 或 Activity 的任何引用; 如果必須,請始終使用 WeakReference。

我通過改變來修復

private val viewModel: MainViewModel by viewModel()

private val viewModel: MainViewModel by inject()

PS:我使用 koin 作為依賴注入器

暫無
暫無

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

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