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)
}
}
}
}
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 }
}