I'm trying to implement a timer using a `LaunchedE...
# compose
s
I'm trying to implement a timer using a
LaunchedEffect
, but it seems that
LaunchedEffect
gets canceled on recompose.
Copy code
@Composable
fun TimeDisplay(viewModel: TimeDisplayViewModel) {
  val properties: Map<String, Long> by viewModel.properties.collectAsState()
  var timeRemaining by rememeber { mutableStateOf(0) }
  
  Text(timeRemaining.toString)
  
  val timeProperty = properties["time"]
  LaunchedEffect(timeProperty) {
    val currentTime = System.currentTimeMillis()
    while (timeProperty > currentTime) {
      timeRemaining = timeProperty - currentTime
      delay(1000L)
    }
    timeRemaining = 0L
  }
}
The
LaunchedEffect
is always canceled during the delay.
properties
is updated with an unrelated value.
s
How does
LaunchEffect
check for key equality? If it’s referential equality,
timeProperty
seems to be re-calculated on every recomposition and that could cancel the previous
LaunchedEffect
and launch a new one, meaning that the previous coroutine would be canceled. The first time it suspends and finds an opportunity to stop working is inside the
delay
function. Could you try replacing
Copy code
val timeProperty = properties["time"]
with
Copy code
val timeProperty by remember(properties) {
    properties["time"]
}
And see if that helps? This is a wild guess, but that’s what I’d try myself first
s
I thought it was value equality, but I haven't checked. It would actually be fine if it stopped the old instance and launched a new one, but it just stops the old one, so I think something else is going on. I ended up moving it into a flow in the view model, which I guess might be a cleaner solution anyway. Thanks for your answer. I still wonder why the
LaunchedEffect
was canceled and not re-launched.
s
Btw now that I read it again. Your loop seems to never really end though. You are checking for
timeProperty
and
currentTime
which both don’t seem to change inside the while loop. Shouldn’t the
currentTimeMillis()
be taken again after the delay?
s
Yeah, you're right about that. I think it was a mistake in translation from the actual code, but maybe not.
s
Guess we’ll never know 😅