Issue
I have a LiveData<Map<A, List<B >>
that comes from Room Database and I have also a searchQuery that I want to Filter the B objects by. For example,
data class Server(
val serverId: Int
)
data class Group(
val serverId: Int,
val groupId: Int,
val description: String
)
LiveData<Map<Server, List<Group>>
So I have
Server(100)
Group(100, 1, "AAAA")
Group(100, 2, "AAAB")
Group(100, 3, "AABB")
Server(200)
Group(200, 1, "AAAA")
Group(200, 2, "AAAB")
Group(200, 3, "AABB")
Now, I have a searchableString = "BB"
So the LiveData I want it to be filtered on the description field and the result must be
Server(100)
Group(100, 3, "AABB")
Server(200)
Group(200, 3, "AABB")
Is there any way to do this on Kotlin?
Solution
First write an extension function to filter your map:
fun Map<Server, List<Group>>.filterGroups(descFilter: String) = mapValues { _, groups ->
groups.filter { descFilter in it.description }
}
If you want to eliminate empty servers, you could tack on a .filter { _, groups -> groups.isNotEmpty() }
to the end of the above function.
Assuming your LiveData is in a view model, I would create a private MutableLiveData for the search term with a public property to change it. Then use switchMap
to produce the final result based on your input.
val sourceMapFromRoom: LiveData<Map<Server, List<Group>> = //...
private val _searchFilter = MutableLiveData<String>("")
val searchFilter: String
get() = _searchFilter.value
set(value) { _searchFilter.value = value }
val filteredMap = _searchFilter.switchMap { searchString ->
sourceMapFromRoom.map { it.filterGroups(searchString) }
}
switchMap
is the LiveData equivalent of flatMapLatest
in Rx or Kotlin Flows.
Answered By - Tenfour04
Answer Checked By - Pedro (JavaFixing Volunteer)