корутин котлина используется внутри модифицированного livedata . Запуск счетчика и его отмена

#android #kotlin-coroutines #android-livedata

Вопрос:

Мне нужна ваша помощь, есть livedata, которая возвращает логическое значение, которое постоянно меняется. Мне нужно, чтобы при выполнении true сопрограмма выполнялась (есть просто имитация процентов загрузки от 0 до 100%), соответственно, false отменяет ее и так далее по кругу.

если он возвращает значение 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
    }
}
 

Ответ №1:

Вы должны переопределить свой счетчик, вы запускаете сопрограмму, которая запускает сопрограмму, которую можно превратить всего в одну запущенную сопрограмму. И для того, чтобы отменить сопрограмму, вы должны сделать ее совместимой с возможностью отмены.

 private suspend fun counter() {
    while (coroutineContext.isActive amp;amp; 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()
        }
    })
 

Комментарии:

1. Спасибо, я уже немного повозился.

Ответ №2:

запуск возвращает значение a Job , которое вы можете отменить вместо всей области действия сопрограммы.

Поэтому я бы сделал что-то следующее:

  1. Сохраните ссылку на свою работу счетчика: private var counterJob: Job? = null
  2. Обновляйте его по мере необходимости: counterJob = launch { counter() }
  3. Отмените его, когда это необходимо: counterJob?.cancel()

Комментарии:

1. Спасибо за ответ, но в моем случае это не работает. Сопрограмма не отменяется, если получено значение false. Что я делаю не так?

2. В этом случае ссылка не равна нулю, но счетчик продолжает идти