我正在使用以下代码在 jetpack 中尝试 CountDownTimer 组合
@Composable
fun Timer() {
val millisInFuture: Long = 10 * 1000 // TODO: get actual value
val timeData = remember {
mutableStateOf(millisInFuture)
}
val countDownTimer =
object : CountDownTimer(millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
Log.d("TAG", "onTick: ")
timeData.value = millisInFuture
}
override fun onFinish() {
}
}
DisposableEffect(key1 = "key") {
countDownTimer.start()
onDispose {
countDownTimer.cancel()
}
}
Text(
text = timeData.value.toString()
)
}
在 logcat 中,我可以看到计时器正在滴答作响,但 UI 没有更新。 请解释为什么改变状态变量的值会发生重组。
简单的倒数计时器只为第二个
var timer by remember { mutableStateOf(durationSeconds) }
LaunchedEffect(key1 = timer) {
if (timer > 0) {
delay(1_000)
timer -= 1
}
}
Text(
text = timer.toString()
)
嗯,在 CountDownTimer 中,您应该设置 millisUntilFinished,而不是设置 millisInFuture。该变量保存更新后的值,millisInFuture 永远不会改变
timeData.value = millisUntilFinished
您可以尝试使用此代码来实现倒计时器:
val time = (timerDate.time).minus(Calendar.getInstance().timeInMillis)
var timer by remember { mutableStateOf(time) }
LaunchedEffect(key1 = timer) {
if (timer > 0) {
delay(1000L)
timer -= 1000L
}
}
val secMilSec: Long = 1000
val minMilSec = 60 * secMilSec
val hourMilSec = 60 * minMilSec
val dayMilSec = 24 * hourMilSec
val hours = (time % dayMilSec / hourMilSec).toInt()
val minutes = (time % dayMilSec % hourMilSec / minMilSec).toInt()
val seconds = (time % dayMilSec % hourMilSec % minMilSec / secMilSec).toInt()
Text(text = String.format("%02d:%02d:%02d", hours, minutes, seconds))
最简单的解决方案是在几秒钟内进行类似于
countDownTimer
的延迟,如下所示:
@Composable
private fun Timer(
waitingTime: Long = WAITING_TIME_MILLIS,
onFinish: () -> Unit
) = LaunchedEffect(waitingTime) {
delay(waitingTime)
onFinish()
}
仅当可组合函数参数或可组合本身内部
State<T>
的值更改(如mutableStateOf()
或mutableStateListOf()
)发生状态更改时,才可组合。就您而言,您还没有启动 countDownTimer
本身。尝试在 countDownTimer.start()
内调用 DisposableEffect
。其次,您将 timeData 设置为错误的值,尝试使用 millisUntilFinished
设置它