Tre*_*kaz 18 timer kotlin android-jetpack-compose compose-desktop compose-multiplatform
我想编写一些应用程序,让一些事情按计划进行。
每隔几分钟轮询一次 URL 进行更新似乎是一个相当常见的用例。不过,在这种特殊情况下,我只是想实现一个时钟。
这有效:
@Composable
fun App() {
var ticks by remember { mutableStateOf(0) }
// Not 100% happy about this unused variable either
val timer = remember {
Timer().apply {
val task = object : TimerTask() {
override fun run() {
ticks++
}
}
scheduleAtFixedRate(task, 1000L, 1000L)
}
}
MaterialTheme {
Text(
// A real application would format this number properly,
// but that's a different question
text = "$ticks"
)
}
}
Run Code Online (Sandbox Code Playgroud)
但我必须导入java.util.Timer,所以它不会是可移植的。
Jetpack Compose 可以做动画,所以它肯定在某个地方有自己的计时器,这意味着也应该有一些便携的方法来做到这一点,但我似乎无法弄清楚。
有没有跨平台的方法来为此目的获取计时器?
Phi*_*hov 43
在 Compose 中,您可以使用LaunchedEffect- 这是在协程作用域上运行的副作用,因此您可以delay在内部使用,如下所示:
var ticks by remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
while(true) {
delay(1.seconds)
ticks++
}
}
Run Code Online (Sandbox Code Playgroud)
我只是想分享一个我尝试过的替代方案,以防其他人想到它并遇到与我相同的问题。这是简单的实现:
@Composable
fun Countdown(targetTime: Long, content: @Composable (remainingTime: Long) -> Unit) {
var remainingTime by remember(targetTime) {
mutableStateOf(targetTime - System.currentTimeMillis())
}
content.invoke(remainingTime)
LaunchedEffect(remainingTime) {
delay(1_000L)
remainingTime = targetTime - System.currentTimeMillis()
}
}
Run Code Online (Sandbox Code Playgroud)
假设您想要高达一秒的精度,此代码片段将导致在更新LaunchedEffect后更新一秒,更新与当前时间(以毫秒为单位)相关。这基本上创建了一个循环。将此逻辑包装在 a 中是很好的,因为它可以防止在将您嵌入到大型组件树中时导致的过度重新组合。remainingTimeremainingTime@ComposableLaunchedEffect
这可行,但有一个问题:您最终会注意到计时器正在跳过几秒。发生这种情况是因为向变量分配新值remainingTime和重新执行之间会存在一些额外的延迟LaunchedEffect,这本质上意味着更新之间的时间间隔超过一秒。
这是上述内容的改进实现:
@Composable
fun Countdown(targetTime: Long, content: @Composable (remainingTime: Long) -> Unit) {
var remainingTime by remember(targetTime) {
mutableStateOf(targetTime - System.currentTimeMillis())
}
content.invoke(remainingTime)
LaunchedEffect(remainingTime) {
val diff = remainingTime - (targetTime - System.currentTimeMillis())
delay(1_000L - diff)
remainingTime = targetTime - System.currentTimeMillis()
}
}
Run Code Online (Sandbox Code Playgroud)
LaunchedEffect我们只需从预期延迟时间中减去重新执行所需的时间即可。这将避免你的计时器跳秒。
额外的延迟不应成为已接受答案中实施的问题。我注意到这种方法的唯一优点是,一旦我们离开屏幕,循环就会停止运行。在我的测试中,当导航到另一个活动时,带有条件的 while 循环true继续运行。
| 归档时间: |
|
| 查看次数: |
15270 次 |
| 最近记录: |