james04
james04

Reputation: 1920

Filter LiveData<Map> by another LiveData<String> android kotlin

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?

Upvotes: 0

Views: 378

Answers (1)

Tenfour04
Tenfour04

Reputation: 93649

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.

Upvotes: 1

Related Questions