Skip to content

Instantly share code, notes, and snippets.

@NathanSass
Last active August 5, 2021 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NathanSass/7492591a636550d68600ec4c369c547f to your computer and use it in GitHub Desktop.
Save NathanSass/7492591a636550d68600ec4c369c547f to your computer and use it in GitHub Desktop.
A basic type ahead
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.runBlocking
import org.junit.Test
class TypeAheadTest {
private var queryCount = 0
private suspend fun getResultsAsync(query: String): List<String> {
println("Query${queryCount++}: $query")
return if (query == "hell") {
delay(1000) // just to introduce some unexpected delay
listOf("hell, hellfire, hell and fury")
} else if (query == "hello wor") {
listOf("hello world", "hello world!", "hello worms")
} else {
listOf("unknown")
}
}
private val MIN_CHARACHTER_COUNT_FOR_SEARCH = 3
private suspend fun handleTypeAhead(dataSource: Flow<String>, onChange: (results: List<String>) -> Unit) {
// if a user is typing quickly wait for a pause before collecting most recent update. Ignore anything less then 3 characters.
val resultsFromUser = dataSource.debounce(500).filter { it.length > MIN_CHARACHTER_COUNT_FOR_SEARCH }
// make an api call to get results for each user's query
// transformLatest will cancel an older api call if a newer arrives first
// this ensures a user will not see typeahead results for an out of date query
val apiCalls = resultsFromUser.transformLatest {
emit(getResultsAsync(it))
}
// pass the queries onto the subscriber. ex. the view to show these updates
apiCalls.collect {
onChange(it)
}
}
@Test
fun test1() {
val typeAheadResults = flow {
emit("h")
emit("he")
emit("hell")
delay(501)
emit("hello wor")
}
runBlocking {
handleTypeAhead(typeAheadResults) {
println("results: $it")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment