I have a Timer() function to be used as a... timer. A very simple one, it can only be set and its remaining time can be read. No cancel/reset.
I intended to use it as just
var timeLeft by Timer()
timeLeft here is just an Int: write any value to it, the timer starts; read it to know how many seconds are left:
var timeLeft by Timer()
// to start (or restart timer)
timeLeft = 60
// to read time left
CircularProgressIndicator(progress = timeLeft / 60f)
This is what I've done so far:
@Composable
private fun Timer() /* : What? */ {
var timeLeftSeconds by remember { mutableIntStateOf(0) }
var targetTime by rememberSaveable { mutableLongStateOf(0) }
LaunchedEffect(timeLeftSeconds > 0) {
while (timeLeftSeconds > 0) {
delay(1000L)
timeLeftSeconds = (targetTime - currentTimeMillis()).toInt() / 1000
}
}
return /* what?
val setValue = { it: Int ->
timeLeftSeconds = it
targetTime = currentTimeMillis() + timeLeftSeconds * 1000L
}
val getValue = { timeLeftSeconds }
*/
}
But I have no idea how to return something that can be used in by. Nor the return type signature.
Note that setValue has to set also targetTime.
You need to return an object that has a value property.
A
MutableState, for example, has a value property. You could actually just return theMutableStatethat you already use:Returning State objects from composable functions is bad style, though: State should only be passed down in parameters, not passed up as return values.
There are several alternatives: You could create a new class that represents the internal state of the counter. An instance of that class would then be passed to your
Timer()function so it can decrease the timer value. This is how a lot of built-in composables also work.But then again, nothing in your function actually needs compose, so you could just make it a simple class that exposes a value property so that it can be delegated.
One last thing: You start your timer in another composable with
timeLeft = 60. This will be executed every time a recomposition takes place, so the timer may be reset at arbitrary times. To prevent this you should wrap it in a side effect, likeLaunchedEffect.