Skip to content

Instantly share code, notes, and snippets.

@chibatching
Last active May 9, 2024 08:28
Show Gist options
  • Save chibatching/e58fc88fff82b95a2532952c1378213c to your computer and use it in GitHub Desktop.
Save chibatching/e58fc88fff82b95a2532952c1378213c to your computer and use it in GitHub Desktop.
Throttle and Debounce on Flow Kotlin Coroutines
fun <T> Flow<T>.throttle(waitMillis: Int) = flow {
coroutineScope {
val context = coroutineContext
var nextMillis = 0L
var delayPost: Deferred<Unit>? = null
collect {
val current = SystemClock.uptimeMillis()
if (nextMillis < current) {
nextMillis = current + waitMillis
emit(it)
delayPost?.cancel()
} else {
val delayNext = nextMillis
delayPost?.cancel()
delayPost = async(Dispatchers.Default) {
delay(nextMillis - current)
if (delayNext == nextMillis) {
nextMillis = SystemClock.uptimeMillis() + waitMillis
withContext(context) {
emit(it)
}
}
}
}
}
}
}
fun <T> Flow<T>.debounce(waitMillis: Long) = flow {
coroutineScope {
val context = coroutineContext
var delayPost: Deferred<Unit>? = null
collect {
delayPost?.cancel()
delayPost = async(Dispatchers.Default) {
delay(waitMillis)
withContext(context) {
emit(it)
}
}
}
}
}
@amir1376
Copy link

amir1376 commented Aug 6, 2022

Why you used Dispatchers.Default in line 16?
I know that if you don't add this dispacher, code will crash due to IllegalStateException
but I can't figure out how Dispatchers.Default fix that problem

@my-dad
Copy link

my-dad commented Mar 5, 2024

How Can i use this on an activity?

@amir1376
Copy link

amir1376 commented Mar 6, 2024

@my-dad you can use this where ever you want,
no matter in activity or view model etc..

searchTextFlow
  .debaunce(500)
  .onEach{performSearch(it)}
  .launchOn(lifecycleScope)

I should mention that coroutine library already has a debaunce function so you don't need to copy this function anymore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment