Home > Mobile >  Combine Flow<List> and string in kotlin
Combine Flow<List> and string in kotlin

Time:06-13

Hey I am working in kotlin flow. I have flow in which I have list of data coming from server. And I want to filter text, I tried some piece of code but it's giving me problem. Can someone guide me on this. Thanks

ExploreViewModel.kt

class ExploreViewModel : BaseViewModel() {

    private val query = MutableStateFlow("")
    var queryText: String
        get() = query.value
        set(value) {
            query.value = value
        }
    val filteredTopics = MutableStateFlow<List<ConsultationTopics>>(emptyList())
    val filteredCategories = query
        .debounce(200) // low debounce because we are just filtering local data
        .distinctUntilChanged()
        .combine(filteredTopics) { queryText, categoriesList ->
            val criteria = queryText.lowercase()
            if (criteria.isEmpty()) {
                    return@combine filteredTopics
            } else {
                categoriesList.filter { category -> category.title?.lowercase()?.let { criteria.contains(it) } == true }
            }
        }
}

I have filteredTopics property which have all data coming from server, queryText is using onQueryTextChange from serarchview. I am trying to filter the data and create new property called filteredCategories to pass this value to adapter. I am trying in filteredCategories I am checking queryText is empty then passing whole list otherwise pass filter list only, but I don't know this is correct way of doing or not.

Error

private fun setupFilteredTopic() {
        lifecycleScope.launchWhenCreated {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                viewModel.filteredCategories.collect { filteredTopicsList ->
                    consultationAdapter.submitList(filteredTopicsList)
                }
            }
        }
    }

enter image description here

Can someone guide me. Thanks

CodePudding user response:

The problem is that you returning elements of different types for filteredCategories

if (criteria.isEmpty()) {
    return@combine filteredTopics // type MutableStateFlow<List<ConsultationTopics>>
} else {
    categoriesList.filter { category -> category.title?.lowercase()?.let { criteria.contains(it) } == true } // type List<ConsultationTopics>
}

so you need to make a little change to your code, change return@combine filteredTopics by return@combine filteredTopics.value:

class ExploreViewModel : BaseViewModel() {

    private val query = MutableStateFlow("")
    var queryText: String
        get() = query.value
        set(value) {
            query.value = value
        }
    val filteredTopics = MutableStateFlow<List<ConsultationTopics>>(emptyList())
    val filteredCategories = query
        .debounce(200) // low debounce because we are just filtering local data
        .distinctUntilChanged()
        .combine(filteredTopics) { queryText, categoriesList ->
            val criteria = queryText.lowercase()
            if (criteria.isEmpty()) {
                categoriesList
            } else {
                categoriesList.filter { category -> category.title?.lowercase()?.let { criteria.contains(it) } == true }
            }
        }
}

this should fix the error

CodePudding user response:

You should return a list of ConsultationTopics objects in the combine block using categoriesList instead of filteredTopics:

val criteria = queryText.lowercase()
return@combine if (criteria.isEmpty()) {
     categoriesList
} else {
     categoriesList.filter { category -> category.title?.lowercase()?.let { criteria.contains(it) } == true }
}

Or we can omit the return@combine operator:

val criteria = queryText.lowercase()
if (criteria.isEmpty()) {
     categoriesList
} else {
     categoriesList.filter { category -> category.title?.lowercase()?.let { criteria.contains(it) } == true }
}
  • Related