为什么lifecycleScope不等待viewmodelscope完成?

问题描述 投票:0回答:1

我想要一个按钮在导航到另一个片段之前执行 viewmodel 的方法,但似乎在更改屏幕之前它没有等待所有挂起功能完成:

View.class

    nextButton.setOnClickListener {
        val action = FragmentDirections.AToB()
        lifecycleScope.launch {
             getViewModel().doSomething()
             findNavController().safeNavigate(action)
        }
   }

ViewModel.class

suspend fun doSomething() {
    viewModelScope.launch {  //tested with Context.IO and without Context
        // long running suspend fun, or even delay(10000)
        // screen is navigating before previous instruction finishes
    }
}
android kotlin kotlin-coroutines android-lifecycle android-viewmodel
1个回答
0
投票

使用

viewModelScope.launch
会启动单独的协程,可能会导致在正在进行的操作完成之前导航到新屏幕。推荐的方法是在开始导航之前使用
LiveData
观察操作的完成情况。


private val _operationComplete = MutableLiveData<Boolean>()
val operationComplete: LiveData<Boolean>
    get() = _operationComplete

suspend fun doSomething() {
    viewModelScope.launch {
        // Long running suspend fun or delay(10000)
        _operationComplete.value = true
    }
}

在涉及确保及时完成的小型操作的场景中,可以考虑使用

join
,只要它能确保防止 ANR 问题。

suspend fun doSomething() {
    val job = viewModelScope.launch {
        // Long running suspend fun or delay(10000)
    }
    job.join() // Wait for the coroutine to complete
    // Now navigate to the other fragment
}

您还可以创建自定义协程作用域并使用它来启动挂起函数。这样,您可以更明确地控制行为。

private val customScope = CoroutineScope(Dispatchers.Default)

suspend fun doSomething() {
    customScope.launch {
        // Long running suspend fun or delay(10000)
    }.join()
}

根据您的情况,我建议采用第一种方法。快乐编码:)

© www.soinside.com 2019 - 2024. All rights reserved.