Search code examples
kotlintimerandroid-jetpack-composecompose-desktopcompose-multiplatform

How can I implement a timer in a portable way in Jetpack Compose?


There's applications I'd like to write where I'd like some things to occur on a schedule.

Polling a URL for updates every few minutes seems to be a fairly common use case. In this particular case, though, I'm just trying to implement a clock.

This works:

@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"
        )
    }
}

But I had to import java.util.Timer, so it's not going to be portable.

Jetpack Compose can do animation, so it surely has its own timer somewhere, implying there should be some portable way to do this as well, but I can't seem to figure it out.

Is there a cross-platform way to get a timer for this purpose?


Solution

  • In Compose you can use LaunchedEffect - it's a side effect which is run on a coroutine scope, so you can use delay inside, like this:

    var ticks by remember { mutableStateOf(0) }
    LaunchedEffect(Unit) {
        while(true) {
            delay(1.seconds)
            ticks++
        }
    }