【问题标题】:kotlin coroutine use inside a modified livedata <Boolean>. Running a counter and canceling itkotlin 协程在修改后的 livedata <Boolean> 中使用。运行计数器并取消它
【发布时间】:2021-08-14 10:56:05
【问题描述】:

我需要你的帮助,有一个 livedata 返回一个不断变化的布尔值。我需要,当 true 执行协程(只是模拟从 0 到 100% 的加载百分比)时,分别取消它,等等。

如果返回 true,则运行协程,否则取消它

graphicOverlay.onSuccess.observe(viewLifecycleOwner, {
        auraImageView.isInvisible = it != true
        noteScanFaceView.isVisible = it == false
        if (!isFaceDetected) {
            if (it) {
                buttonChangeCameraSelector.isVisible = false
                llScanning.isVisible = true
                viewLifecycleOwner.lifecycleScope.launch {counter()}
                isFaceDetected = true
            } else {

             viewLifecycleOwner.lifecycleScope.cancel()
            }
        }
    })

这是一个计数器

private suspend fun counter() = viewLifecycleOwner.lifecycleScope.launch {
    val job = launch {
        while (progressStatus < 100) {
            progressStatus += 1
            delay(50)
            handler.post {
                textViewPercent.text = "$progressStatus"
            }
        }
    }
    job.join()
    fragmentSendDataListener.onSendResultsModel(resultSendData)
    requireActivity().runOnUiThread {
        llToolbar.isVisible = false
    }
}

【问题讨论】:

    标签: android kotlin-coroutines android-livedata


    【解决方案1】:

    您确实重新定义了您的计数器,您正在启动一个启动一个协程的协程,该协程可以变成一个启动的协程。为了取消协程,您必须使其可协同取消

    private suspend fun counter() {
        while (coroutineContext.isActive && progressStatus < 100) {
            progressStatus += 1
            delay(50)
            handler.post {
                textViewPercent.text = "$progressStatus"
            }
        }
    
        fragmentSendDataListener.onSendResultsModel(resultSendData)
        requireActivity().runOnUiThread {
            llToolbar.isVisible = false
        }
    }
    

    由于启动返回作业,请保留对它的引用,并将其重新定义/取消为 需要。

    private var counterJob: Job? = null
    
    graphicOverlay.onSuccess.observe(viewLifecycleOwner, {
            auraImageView.isInvisible = it != true
            noteScanFaceView.isVisible = it == false
            if (!isFaceDetected) {
                if (it) {
                    buttonChangeCameraSelector.isVisible = false
                    llScanning.isVisible = true
                    counterJob = viewLifecycleOwner.lifecycleScope.launch {counter()}
                    isFaceDetected = true
                } else counterJob?.cancel()
            }
        })
    

    【讨论】:

    • 谢谢,我已经做了一些修改。
    【解决方案2】:

    launch 返回一个Job,您可以取消它而不是整个协程范围。

    所以我会做如下的事情:

    1. 保存对计数器工作的引用:private var counterJob: Job? = null
    2. 需要时更新:counterJob = launch { counter() }
    3. 需要时取消:counterJob?.cancel()

    【讨论】:

    • 感谢您的回答,但在我的情况下不起作用。收到 false 时不会取消协程。我做错了什么?
    • 在这种情况下,链接不为零,但计数器继续走
    猜你喜欢
    • 2021-05-17
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    相关资源
    最近更新 更多