kotlin 协程在修改后的实时数据中使用 <Boolean>。 运行 一个计数器并取消它

kotlin coroutine use inside a modified livedata <Boolean>. Running a counter and canceling it

我需要你的帮助,有一个livedata returns 一个不断变化的布尔值。我需要分别在true时执行协程(只是模拟0到100%的加载百分比),false时取消,依次类推。

如果它 returns 为真,运行 协程否则取消它

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
    }
}

launch returns a Job,你可以取消它而不是整个协程范围。

所以我会做如下事情:

  1. 保存对您柜台工作的参考:private var counterJob: Job? = null
  2. 需要时更新:counterJob = launch { counter() }
  3. 需要时取消:counterJob?.cancel()

你确实重新定义了你的计数器,你正在启动一个启动协程的协程,它可以变成只启动一个协程。为了取消协程,你必须使它可合作取消

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
    }
}

自启动 returns 作业后,保留对它的引用,并将其作为 redefine/cancel 需要。

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()
        }
    })