Avoid wasting API/Local database calls in Android using Debounce in searchbar.


class MainViewModel: ViewModel() {
    private val _searchQueryState = MutableStateFlow("")
    val searchQueryState = _searchQueryState.asStateFlow()

    private val citiesList = listOf<String>(
        "Lahore", "Islamabad", "Quetta", "Karachi", "Peshawar", "Multan", "Hyderabad", "Faisalabad", "Rawalpindi", "Sialkot", "Gujranwala", "Bahawalpur"
    )

    private val _searchResultList = MutableStateFlow<List<String>>(emptyList())
    val searchResultList = _searchResultList.asStateFlow()

    fun updateSearchQuery(query: String){
        _searchQueryState.value = query
    }

    init {
        viewModelScope.launch {
            _searchQueryState
                .debounce(600)
                .distinctUntilChanged()
                .mapLatest { query ->
                    filterCities(query)
                }
                .collect {filteredList ->
                    _searchResultList.value = filteredList
                }
        }
    }

    fun filterCities(query: String): List<String>{
        return citiesList.filter {
            it.contains(query, ignoreCase = true)
        }
    }
}

Utilize in Composable.



@Composable
fun MainCompose(
    searchQuery: String,
    onQueryChange: (String) -> Unit,
    searchResultList: List<String>
){
    Scaffold {innerPadding ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(innerPadding)
        ){
            Column(
                modifier = Modifier.padding(16.dp)
            ) {
                SearchBox(
                    modifier = Modifier.fillMaxWidth(),
                    query = searchQuery,
                    onQueryChange = { onQueryChange(it) },
                )
                Spacer(modifier = Modifier.height(16.dp))
                SearchResultList(searchResultList = searchResultList)
            }
        }

    }
}

@Composable
fun SearchResultList(searchResultList: List<String>) {
    LazyColumn{
        items(items = searchResultList){ item ->

            Text(
                text = item,
                style = MaterialTheme.typography.labelLarge,
                modifier = Modifier.padding(4.dp)
            )
            HorizontalDivider()
            Spacer(modifier = Modifier.height(4.dp))
        }
    }
}
Code language: JavaScript (javascript)

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
AndroidPlaygroundAppTheme {
val viewModel = viewModel<MainViewModel>()
MainCompose(
searchQuery = viewModel.searchQueryState.collectAsStateWithLifecycle().value,
onQueryChange = { viewModel.updateSearchQuery(it) },
searchResultList = viewModel.searchResultList.collectAsStateWithLifecycle().value
)
}
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *