Ky
02/15/2021, 2:53 AMFlow
.
So this works as expected
CoroutineScope(IO).launch {
flow<Int>{
emit(1)
delay(350)
emit(2)
delay(100)
emit(3)
}.debounce(300)
.collect {
Timber.d(it.toString())
}
}
Output: 1, 3
However trying to apply this same idea to a searchview I have..
TextField(
modifier = Modifier
.fillMaxSize()
.background(
color = MaterialTheme.colors
.elevatedSurface(3.dp)
.copy(alpha = 0.95f)
),
value = searchTerm.value, onValueChange = { newValue ->
searchTerm.value = newValue
CoroutineScope(IO).launch {
queryFlow(newValue.text, viewModel)
}
})
This is queryFlow
suspend fun queryFlow(query: String, viewModel: TwitMainViewModel) = flow {
Timber.d("Emitting: ${query}")
emit(query)
delay(500)
}.debounce(1000)
.filterNot {
it.isEmpty()
}
.collect {
Timber.d("MAKING REQUEST FOR: $it")
viewModel.search(it)
}
So in this case, even if I rapid type nnn
a request is made for each; being n
nn
and nnn
. The debounce operator has no effect here. I can’t identify why however, any ideas?
ThanksAdam Powell
02/15/2021, 3:03 AMonValueChange
runs for every change request from the text field, so this is going to launch a new independent query coroutine for each change that happens. The debounce will delay a search request, but since each request is independent, it won't have the intended effect.Adam Powell
02/15/2021, 3:03 AMAdam Powell
02/15/2021, 3:08 AM// remember a channel we can send to.
// Conflated because we want old values to be replaced by new.
// queryChannel.offer will always succeed.
val queryChannel = remember { Channel<String>(Channel.CONFLATED) }
// LaunchedEffect will run our queries and cancel everything when
// this composable leaves the composition. If we get a different
// viewModel object this will cancel the old effect and launch a new one.
LaunchedEffect(viewModel) {
// Use withContext here to change dispatchers if desired
queryChannel.receiveAsFlow()
.debounce(1000)
.filterNot { it.isEmpty() }
.collect {
viewModel.search(it)
}
}
TextField(
// ...
onValueChange = { newValue ->
searchTerm.value = newValue
queryChannel.offer(newValue.text)
}
)
Adam Powell
02/15/2021, 3:11 AMAlbert Chang
02/15/2021, 3:15 AMCreates a cold flow from the given suspendable block. The flow being cold means that the block is called every time a terminal operator is applied to the resulting flow.
Ky
02/15/2021, 2:07 PM