1

I'm creating a custom Progress UI component that animates the progress using animateFloatAsState like so:

@Composable 
fun CustomProgressBar(progressValue: Float = 0f) {

val animatedProgress by
          animateFloatAsState(
              targetValue = progressValue,
              animationSpec = TweenSpec(durationMillis = 500, easing = LinearEasing))

LinearProgressIndicator(progress = animatedProgress)
}

How can I ensure someone using this component doesn't update the progressValue so often that the animation will look janky?

Can this be throttled within the Composable? Or should this be the responsibility of the caller?

  • While I agree with the accepted answer's general approach of debouncing, I would argue that this is the responsibility of the data source. I assume that `progressValue` is coming from something like a viewmodel -- if so, it should be doing the debouncing IMHO. It should be easier to test the debounce logic there. – CommonsWare Aug 27 '23 at 13:08

1 Answers1

2

You can use Debounce Approach to drop frequent values which will reduce the throttling. You have to change the way by which the progressValue is update and so the composable. So you just update the value smoothly so there will be less throttling.

Here is the example of the Debounce approach you can use...

// Use to compose the progress bar composable
val progress = mutableStateOf(0f)

// Instance of job to use for cancellation
var job: Job? = null

private fun updateProgress(newValue: Float) {
    // Previous job will be cancelled if not completed
    job?.cancel()

    // Use any suitable coroutineScope to launch the work
    job = lifecycleScope.launch {
        // 1 second wait to get the next value
        delay(1000)

        // If no updated value is there within waiting time then updating the progress value
        progress.value = newValue
    }
}
//...

Here we are waiting for some time to check if there is any frequent new value if there then we will cancel the previous update and again schedule our update after waiting to get assigned to the progressValue.

You can also use flows to update the progressValue and flows has built-in Debounce Technique. You can check the kotlin debounce docs at: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/debounce.html

Atul Sharma
  • 399
  • 3
  • 12