kdux.tools.DebounceEnhancer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Kdux Show documentation
Show all versions of Kdux Show documentation
Kdux is a Kotlin-based, platform-agnostic state management library that implements the Redux pattern,
providing structured concurrency with built-in coroutine support. It is designed to integrate seamlessly
with any Kotlin project, particularly excelling in Android applications using MVI architecture.
package kdux.tools
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.mattshoe.shoebox.kdux.Enhancer
import org.mattshoe.shoebox.kdux.Store
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
import kotlin.time.TimeSource
private val LONG_TIME_FROM_NOW = 10.days
/**
* An enhancer that debounces dispatched actions based on a specified time duration.
* This means that actions will only be dispatched if a specified amount of time has passed
* since the last dispatched action. If actions are dispatched more frequently than the
* debounce duration, only the first action in the burst will be dispatched.
*
* In other words, if you try to dispatch more than one action in a given [duration], then
* all actions besides the first will be DROPPED. They will not be queued to execute later.
*
* This enhancer is useful in scenarios where you want to limit the rate at which actions
* are processed, such as preventing excessive updates in response to rapid user input.
*
* @param duration The debounce duration. Actions will only be dispatched if this amount
* of time has passed since the last dispatched action.
*
* @throws IllegalArgumentException if `duration` is less than or equal to zero.
*/
class DebounceEnhancer(
private val duration: Duration
): Enhancer {
init {
require(duration > Duration.ZERO) {
"Debounce duration must be greater than zero."
}
}
override fun enhance(store: Store): Store {
return object : Store {
private val timeSource = TimeSource.Monotonic
private val now: TimeSource.Monotonic.ValueTimeMark get() = timeSource.markNow()
private var debounceStart = now.minus(LONG_TIME_FROM_NOW)
private val elapsedTimeSinceLastDispatch: Duration get() = now.minus(debounceStart)
private val debounceMutex = Mutex()
override val state: Flow
get() = store.state
override val currentState: State
get() = store.currentState
override suspend fun dispatch(action: Action) {
var actionToDispatch: Action? = null
debounceMutex.withLock {
if (elapsedTimeSinceLastDispatch > duration) {
actionToDispatch = action
debounceStart = now
}
}
actionToDispatch?.let {
store.dispatch(it)
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy