Implement Instant Search Using Kotlin Flow Operators
Last Updated :
14 Sep, 2022
A flow is a type in coroutines that can emit multiple values sequentially, as opposed to suspend functions, which only return a single value. A flow, for example, can be used to receive real-time updates from a database. Flows are constructed on top of coroutines and can return multiple values. A flow is a stream of data that can be computed asynchronously. All the outputs of the flow must be of the same type. A FlowInt, for example, is a flow that emits integer values. A flow is similar to an Iterator in that it produces a sequence of values, but it produces and consumes values asynchronously by using suspend functions. This means that the flow, for example, can safely make a network request to generate the next value without blocking the main thread.
The following Kotlin Flow features will be used to implement this search feature:
- StateFlow: We’ve already written an article about it. You can find out more about it right here.
- Operator of a Debounce
- Operator of a Filter
- Operator DistinctUntilChanged
- Latest FlatMap Operator
Previously, implementing this instant search feature in Android was difficult with Kotlin Coroutines, but with Kotlin Flow Operators, it has become simple and interesting.
Let’s get started
First and foremost, we will write an extension function that returns the StateFlow so that we can apply the necessary operators to it. So, on the SearchView, we’ll use the setOnQueryTextListener to watch for changes in the text, change the query’s state, and finally return the StateFlow as shown below:
Kotlin
fun GfGSearch.getQueryTextChangeStateFlow(): StateFlow<String> {
val searchQuery = MutableStateFlow( "Geeks" )
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onSearchSubmit(query: String?): Boolean {
return true
}
override fun onTermChange(newText: String): Boolean {
searchQuery.value = newText
return true
}
})
return searchQuery
}
|
Then in order to test this, we take some pseudo network exchange for the data.
Kotlin
private fun someDataFetch(query: String): Flow<String> {
return flow {
delay( 1500 )
emit(gfgDataQuery)
}
}
|
Now, on the QueryTextChangeStateFlow, we will use the following operators:
Kotlin
gfgSerachView.getQueryTextChangeStateFlow()
.debounce( 600 )
.filter { searchQuery ->
if (searchQuery.isEmpty()) {
textViewResult.text = "Geeks"
return @filter false
} else {
return @filter true
}
}
.distinctUntilChanged()
.flatMapLatest { searchQuery ->
dataFromNetwork(searchQuery)
. catch {
emitAll(flowOf( "Geeks" ))
}
}
.flowOn(Dispatchers.Default)
.collect { result ->
sometxtView.text = result
}
|
It’s time to learn why the above operators are used and how they work when combined.
Recognizing Operators
- Debounce: The debounce operator is used with a time constant in this case. When the user types “a”, “ab”, or “abc” in a short period of time, the debounce operator handles the case. As a result, there will be a large number of network calls. However, the user is ultimately interested in the “abc” search result. As a result, the results of “a” and “ab” must be discarded. There should ideally be no network calls for “a” and “ab” because the user typed those in a very short period of time.
- Filter: In this case, the filter operator is used to filter out the unwanted string, which is an empty string, in order to avoid making an unnecessary network call.
- The distinctUntilChanged: Simply used to avoid duplicate calls over the desired network layer. Assume the most recent ongoing search query was “abc,” and the user deleted “c” before typing “c” again. So it’s “abc” once more. Otherwise, any further network call will make the search return a duplicate query increasing the load on the server and thus preventing the source from emitting duplicate consecutive items.
- FlatMapLatest: This is used so that all the pre-fetched stale results are not shown to the users in a situation like a network drop. Assume the most recent search query was “ab,” there is an ongoing network call for “ab,” and the user typed “abc.” Then we’re no longer interested in the outcome of “ab.” We are only concerned with the outcome of “abc.” As a result, flatMapLatest comes to the rescue. It only returns the results of the most recent search query and ignores the rest.
GeekTip: Please keep in mind that if there is an error in the flatMapLatest, we pass the empty result. This can be changed based on our needs.
In this manner, we can implement the instant search feature in an Android application using Kotlin Flow Operators.
Similar Reads
Implement Search Using RxJava Operators
Nowadays, most of the programs we use in our everyday lives include a search option that allows us to easily find what we're looking for. As a result, having a search tool is critical. And it is our job as developers to implement it better. Let's look at how to do it better with the RxJava Operators
4 min read
Retrieve Single Elements In Kotlin
Kotlin Collections allows to retrieve single elements with respect to different conditions. It totally depends on what kind of Collection is used to store the data. The elements of a collection can be retrieved by position, condition, randomization and with respect to the existence of that element i
4 min read
Kotlin - Collection Operations Overview
The Kotlin standard library provides a wide range of functions for performing operations on collections. It includes simple operations like getting or adding elements and also includes more complex ones like searching, sorting, filtering, etc. Member and Extension functions - Collection operations a
4 min read
Kotlin Collection Write operations
Collection Write operations are used to change the content of MutableCollection. MutableCollection is defined as the Collection with write operations like add and remove. Operations supported are as follows: Adding elements Removing elements and Updating elements Addition of elements - add() functio
4 min read
Implement Lazy List in Kotlin
If the value of an element or expression is not evaluated when it's defined, but rather when it is first accessed, it is said to be lazily evaluated. There are many situations where it comes in handy. For example, you might have a list A and you want to create a filtered list from it, let's call it
3 min read
Kotlin Collections Ordering
There are certain collections where the order of the elements is important. If you take lists, two lists are never equal if they are ordered differently inspite of having same elements.In Kotlin, there are different ways of ordering the elements. Most built-in types are comparable: -Numeric types fo
4 min read
Using Query DSL For Complex Search Queries in Elasticsearch
Elasticsearch is a powerful search engine that provides a flexible and powerful query language called Query DSL (Domain Specific Language). Query DSL allows you to write complex search queries to retrieve the most relevant data from your Elasticsearch indices. This article will guide you through the
6 min read
How to Iterate Over a Class's Properties in Kotlin?
Kotlin is a statically typed, general-purpose programming language developed by JetBrains, that has built world-class IDEs like IntelliJ IDEA, PhpStorm, Appcode, etc. It was first introduced by JetBrains in 2011 and is a new language for the JVM. Kotlin is an object-oriented language, and a âbetter
3 min read
How to Work with Inline Properties in Kotlin?
In this article, we are going to discuss how to work with inline properties in Kotlin. but before that, you should know some basics of functions and should be familiar with OOPs concepts. A great thing about Kotlin is high-order functions that let us use functions as parameters to other functions. H
3 min read
Kotlin | Plus and minus Operators
In Kotlin, plus and minus operators are used to work with the list of objects which is usually referred to as Collections (List, Set, Maps). As the name suggests, plus operator adds up or concatenates the elements or objects of the given collections. The elements of the first collection remains as i
2 min read