I have to move a progress bar within a time frame, for example within 6s. I am using coroutines and the "repeat" function. The code executes except that the total execution time is not as specified. Below is my code.
val progressJob = Job()
var startTime = 0L
CoroutineScope(Dispatchers.Default + progressJob).launch {
startTime = System.currentTimeMillis()
repeat(1000) {
progressBar.progress += 1
delay(6)
}
Log.d(TAG, "total time= ${System.currentTimeMillis() - startTime}")
}
I am expecting "total time" would be 6000, but I am getting values greater than 6000 by at least 500.
Basically I just want to repeatedly increment the progress bar within a time frame, and I am not using animation because of performance issue.
Is there anything I am missing?
I would do it with something like this:
withTimeout(1300L) {
repeat(1000) { i ->
println("Blip Blop $i ...")
delay(500L)
}
}
For more examples see official doc: https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html
so what you are doing here is simulating progress. Ideally, there would be some way of checking the actual progress of your bar, and updating it, and when it is done, ending. But, if this is not possible, then ya, simulation is your choice.
So, with coroutines we are dealing with a threaded environment, and within that, we have our coroutines which need to be continued when the hand over control of execution. In your implementation, this happens at the delay
call. For this reason, it is very difficult to guarantee that your coroutine will complete in your desired time. All delay can do is say that it will not resume before "at least" the specified time has elapsed, and probably quite often, more time would have elapsed, not the exact time.
So, how do we get this to execute in as close to your desired time frame as possible? What we need to do is drop the repeat
, and rather check on the elapsed time to decide if we finish. Here is a rough implementation that will hopefully help.
class Bar(val barLength: Int = 1000) {
var progress = 0
}
suspend fun simulateProgress(bar: Bar, job: Job, totalDurationMillis: Long, incrementsMills: Long): Job {
var startTime = System.currentTimeMillis()
return CoroutineScope(Dispatchers.Default + job).launch {
var totalElapsed = 0L
while (totalElapsed < totalDurationMillis) {
totalElapsed = System.currentTimeMillis() - startTime
val progressRatio = totalElapsed.toDouble()/totalDurationMillis.toDouble()
bar.progress = (progressRatio * bar.barLength.toDouble()).toInt()
delay(incrementsMills)
}
println("Elapsed: $totalElapsed, Progress: ${bar.progress}")
}
}
fun main() = runBlocking {
val job = Job()
val bar = Bar()
val progressJob = simulateProgress(bar, job, 6000, 10)
progressJob.join()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With