带Kotlin流的Android CountDownTimer

cnh2zyt3  于 2023-02-02  发布在  Android
关注(0)|答案(2)|浏览(167)

我在实现Android定时器用例时遇到了一些问题,该用例应该返回一个Kotlin流。
用例的invoke()函数接受***LocalDateTime***,并且应该在每次滴答时返回Flow<String>
这是我构建用例代码的方式:

class CountDownUseCase {

    operator fun invoke(launchDate: LocalDateTime): Flow<String> {
        ...
     override fun onTick(millscUntilFinish: Long) {

         //getting error here 
         emit(remaingTimeString)    }
     override fun onFinish() {...   }
    }

这是我在emit()上遇到的错误- * 只能在协程体中调用Suspension函数 *

这是一个更好的图片完整的代码

operator fun invoke(launchDate: LocalDateTime): Flow<String> =
        flow {
            var remainingTimeString: String = ""
            val currentDateTime = System.currentTimeMillis()

            //convert LocalDateTime to millis
            val zdt = launchDate.atZone(ZoneId.systemDefault())
            val futureLaunchDate = zdt.toInstant()
                    .toEpochMilli()
            val timeDifference = futureLaunchDate - currentDateTime

            val countDownTimer = object : CountDownTimer(timeDifference, 1000) {
                override fun onTick(millscUntilFinish: Long) {
                    remainingTimeString = """
                   
                   ${TimeUnit.MILLISECONDS.toDays(millscUntilFinish)}:
                   ${TimeUnit.MILLISECONDS.toHours(millscUntilFinish) % 24}: 
                   ${TimeUnit.MILLISECONDS.toMinutes(millscUntilFinish) % 60}:
                   ${TimeUnit.MILLISECONDS.toSeconds(millscUntilFinish) % 60}
                """.trimIndent()

                    emit(remainingTimeString)
                }

我已经四处寻找,但无法找到一种方法来发出流与每个计时器滴答声。
我将感谢任何帮助去返回一个流每次onTick()覆盖函数被调用。

ubbxdtey

ubbxdtey1#

实现这一点的一个简单方法是用suspendlambda函数 Package emit调用:

suspend {
  emit(remainingTimeString)
}

但我不推荐它,因为使用CountDownTimer应该被一种更令人钦佩的逻辑所取代,它可以直接适应协程作用域,而不需要使用"缝合"。我不推荐它,因为它必须正确地停止和清理,否则,它可能会导致内存问题(泄漏)。
例如,看一下下面的示例:
https://stackoverflow.com/a/63939980/1537916
或者这个:
https://stackoverflow.com/a/54828055/1537916

qojgxg4l

qojgxg4l2#

Android CountDownTimercallbackFlow的示例

class CountDownTimerWrapper(total: Long, interval: Long, onFinish: () -> Unit) {
    private lateinit var countDownTimer: CountDownTimer

    val flow: Flow<Long> = callbackFlow {
        countDownTimer = object : CountDownTimer(total, interval) {
            override fun onTick(millisUntilFinished: Long) {
                trySend(millisUntilFinished)
            }

            override fun onFinish() {
                onFinish()
            }
        }

        awaitClose { countDownTimer.cancel() }
    }

    fun start() {
        countDownTimer.start()
    }
}

相关问题