如何在 Jetpack Compose 中重构每一分钟?

Dun*_*Luk 9 android kotlin android-jetpack android-jetpack-compose

我想在我的可组合项中显示一个倒计时计时器,但我不确定如何实现这一点。

我正在考虑设置一分钟的延迟/超时并以这种方式触发重组,但我不确定这是否是正确的思考方式。

@Composable
fun Countdown(completedAt: Date) {
    val minutesLeft = ceil((completedAt.time - Date().time) / 60_000.0).toInt()

    Handler(Looper.getMainLooper()).postDelayed({
        // TODO: Recompose
    }, 60_000)

    Text(text = "$minutesLeft minutes until completed")
}
Run Code Online (Sandbox Code Playgroud)

我的目标是让文本每分钟更新一次新时间。我怎样才能做到这一点?

Kur*_*ikS 7

@Composable
fun minutesLeft(until: Date): Int {
    var timeout by remember { mutableStateOf(getMinutesLeft(until)) }

    Text(text = "$timeout minutes until completed")

    LaunchedEffect(timeout) {
        if (timeout > 0) {
            delay(1000 * 60)
            timeout -= 1
        }
    }
}

private fun getMinutesLeft(until: Date): Int {
    return ceil((until.time - Date().time) / 60_000.0).toInt()
}
Run Code Online (Sandbox Code Playgroud)


Dun*_*Luk 5

将分钟数存储为状态。

还要确保清理postDelayeda 内的回调DisposableEffect,以防止延迟冲突和内存泄漏。

我已将此逻辑移至可minutesLeft组合函数,以便可以重用。

@Composable
fun minutesLeft(until: Date): Int {
    var value by remember { mutableStateOf(getMinutesLeft(until)) }

    DisposableEffect(Unit) {
        val handler = Handler(Looper.getMainLooper())

        val runnable = {
            value = getMinutesLeft(until)
        }

        handler.postDelayed(runnable, 60_000)

        onDispose {
            handler.removeCallbacks(runnable)
        }
    }

    return value
}

private fun getMinutesLeft(until: Date): Int {
    return ceil((until.time - Date().time) / 60_000.0).toInt()
}
Run Code Online (Sandbox Code Playgroud)

用法

@Composable
fun Countdown(completedAt: Date) {
    val minutes = minutesLeft(until = completedAt)

    Text(text = "$minutes minutes until completed")
}
Run Code Online (Sandbox Code Playgroud)