I use the following code to create a fake implemen...
# coroutines
f
I use the following code to create a fake implementation of a countdown timer based on Coroutines. Can someone tell me if this will be exact or if I need to calculate the time difference in some other way? (see thread)
👀 1
Copy code
class FakeTimer(private val scope: CoroutineScope) : Timer {

    private var millisUntilFinished = 0L

    private var timerJob: Job? = null

    override fun startTimer(
        millisInFuture: Long,
        countDownInterval: Long,
        onTick: (Long) -> Unit,
        onFinish: () -> Unit
    ) {
        millisUntilFinished = millisInFuture
        timerJob = scope.launch {
            while (true) {
                if (millisUntilFinished > countDownInterval) {
                    delay(countDownInterval)
                    onTick(millisUntilFinished)
                    millisUntilFinished -= countDownInterval
                } else {
                    delay(millisUntilFinished)
                    millisUntilFinished = 0L
                    onTick(millisUntilFinished)
                    break
                }
            }
            onFinish()
        }
    }

    override fun cancelTimer() {
        timerJob?.cancel()
    }
}
d
Upon cancelation I would also nullify the old Job. Seems ok, have you unit tested it?
n
It will be off by how long
onTick
takes. If you wait 10 millis and then
onTick
takes 3 millis, the second
onTick
will happen after 23 millis, not after 20 millis.
There's also an added delay in the fact that it'll take some time for launch to actually dispatch the started coroutine.
The time that it's off by will accumulate every time it calls onTick.
And
delay
may take time to resume also because of dispatch.
c
Establishing the target time using system.getTimeMillis and then adjusting based on distance from target will keep the error small especially if you measure the overheads as you go.
f
Thank you, that's what I thought
I guess I have to calculcate the time difference then
This should always be exact, right?
Copy code
fun startTimer(
    millisInFuture: Long,
    countDownInterval: Long,
    onTick: (Long) -> Unit,
    onFinish: () -> Unit
) {
    millisUntilFinished = millisInFuture
    timerJob = scope.launch {
        val startTime = timeSource.elapsedRealTime
        val targetTime = startTime + millisInFuture
        while (true) {
            if (timeSource.elapsedRealTime < targetTime) {
                delay(countDownInterval)
                millisUntilFinished = targetTime - timeSource.elapsedRealTime
                onTick(millisUntilFinished)
            } else {
                onFinish()
            }
        }
    }
}